13 ms·
> SQLite isn't just on the same machine as your application, but actually built into your application process. When you put your data right next to your applica
by bob1029 5y ago
> SQLite isn't just on the same machine as your application, but actually built into your application process. When you put your data right next to your application, you can see per-query latency drop to 10-20 microseconds. That's micro, with a μ. A 50-100x improvement over an intra-region Postgres query.
This is the #1 reason my exuberant technical mind likes that we use SQLite for all the things. Latency is the exact reason you would have a problem scaling any large system in the first place. Forcing it all into one cache-coherent domain is a really good way to begin eliminating entire universes of bugs.
Do we all appreciate just how much more throughput you can get in the case described above? A 100x latency improvement doesn't translate directly into the same # of transactions per second, but its pretty damn close if your I/O subsystem is up to the task.
- overview 5y ago> Latency is the exact reason you would have a problem scaling any large system in the first place. Not always. It depends on the architecture and your hosting strategy. I think it’s more likely for an instance of a web app to receive more requests than it can handle, causing the app to not service any requests.
- closeparen 5y agoThis is a large part of what Rich Hickey emphasizes about Datomic, too. We're so used to the database being "over there" but it's actually very nice to have it locally. Datomic solves this in the context of a distributed database by having the read-only replicas local to client applications while the transaction-running parts are remote.
- abraxas 5y agoOnly trouble with that particular implementation is that the Datomic Transactor is a single threaded single process that serializes every transaction going through it. As long as you don't need to scale writes it works like a charm. However, the workloads I somehow always end up working with are write heavy or at best 50/50 between read and write.
- carry_bit 5y agoThat's another trait it would share with SQLite + litestream, until SQLite's BEGIN CONCURRENT is released.
- carry_bit 5y agoIt's exciting to see Datomic's architecture realized using more conventional technology.
- vmception 5y ago> SQLite isn't just on the same machine as your application, but actually built into your application process. How is that different than whats commonly happening? Android and iOS do this... right? ... but its still accessing the filesystem to use it. Am I missing something or is what they are describing just completely commonplace that is only interesting to people that use microservices and never knew what was normal.
- mrkurt 5y agoThis is how client apps use sqlite, yes. Single instance client apps. Litestream is one method of making sqlite work for server side apps. The hard part on the server is solving for multiple processes/vms/containers writing to one sqlite db.
- vmception 5y agointeresting, such a weird way to describe it then. but I guess some people are more familiar with that problem.
- nicoburns 5y ago> the hard part on the server is solving for multiple processes/vms/containers writing to one sqlite db. I feel like if you have multiple apps writing to the database then you shouldn't be using SQLite. That's where Postgres etc completely earn their place in the stack. Where litestream is really valuable is when you have a single writer, but you want point-in-time backups like you can get with postgres.
- mrkurt 5y agoWe disagree, a little. I feel like that if you have multiple apps writing to the DB, Litestream is pretty close to making sqlite viable for a lot more apps.
- tlb 5y agoIt's normal (and HN does something similar, working from in-process data) for systems that don't have to scale beyond one server. If you need multiple servers you have to do something, such as Litestream.
- WJW 5y agoHow do any writes end up on other horizontally scaled machines though? To me the whole point of a database on another machine is that it is the single point of truth that many horizontally scaled servers can write to and read each others' updates from. If you don't need that, you might as well read the entire dataset into memory and be done with it. I know TFA says that you can "soon" automagically replicate your sqlite db to another server, but it only allows writes on a single server and all other will be readers. Now you need to think about how to move all write traffic to a single app server. All writes to that server will still take several milliseconds (possibly more, since S3 is eventually consistent) to propagate around all replicas. In short, 100x latency improvement for reads is great but a bit of a red herring since if you have read-only traffic you don't need sqlite replication. If you do have write traffic, then routing it through S3 will definitely not give you a 100x latency improvement over Postgres or MySQL anymore. Litestream is definitely on my radar, but as a continuous backup system for small apps ("small" meaning it runs and will always run on a single box) rather than a wholesale replacement of traditional client-server databases. PS: Congrats Ben!
- nicoburns 5y ago> If you don't need that, you might as well read the entire dataset into memory and be done with it. Over in-memory data structures,SQLite gives you: - Persistence - Crash tolerance - Extremely powerful declarative querying capabilities > if you have read-only traffic you don't need sqlite replication. I agree with you that the main use-case here is backup and data durability for small apps. Which is pretty big deal, as a database server is often the most expensive part of running a small app. That said, there are definitely systems where latency of returning a snapshot of the data is important, but which snapshot isn't (if updates take a while to percolate that's fine).
- mbreese 5y agoI’d argue that persistence also includes data portability. It’s very handy to be able to just copy your data around in a SQLite file. That’s not really a feature that’s terribly useful in a remote deployed application, but very handy if you have multiple applications all reading the same data.
- judofyr 5y ago> Latency is the exact reason you would have a problem scaling any large system in the first place. Let's not forget why we started using separate database server in the first now… A web server does quite a lot of things: Parsing/formatting HTTP/JSON/HTML, restructuring data, calculating stuff. This is typically very separate from the data loading aspect and as you get more requests you'll have to put more CPU in order to keep up (regardless of the language). By separating the web server from the database server you introduce more latency in favor of enabling scalability. Now you can spin up hundreds of web servers which all talk to a single database server. This is a typical strategy for scalability: decouple the logic and scale up individually. If you couple them together it's more difficult to scale. First of all, in order to spin up a server you need a full version of the database. Good luck autoscaling on-demand! Also, now every write will have to be replicated to all the readers. That's a lot more bandwidth. There are definitely use cases for Litestream, but it's far from a replacement for your typical Node + PostgreSQL stack. I can see it being useful as a lower-level component: You can use Litestream to build your "own" database server with customized logic which you can talk to using an internal protocol (gRPC?) from your web servers.
- nicoburns 5y ago> There are definitely use cases for Litestream, but it's far from a replacement for your typical Node + PostgreSQL stack If you're a language like Node.js then horizontal scaling makes a lot of sense, but I've been working with Rust a lot recently. And Rust is so efficient that you typically end up in a place where a single application server can easily saturate the database. At that point moving them both onto the same box can start to make sense. This is especially true for a low-traffic apps. I could probably run most of my Rust apps on a VM with 128MB RAM (or even less) and not even a whole CPU core and still get excellent performance. In that context, sticking a SQLite database that backs up to object storage on the same box becomes very attractive from a cost perspective.
- judofyr 5y agoThis is "vertical scaling" and that is indeed a very valid approach! You just have to be aware that vertical scaling has some fundamental limits and it's going to suck big time if it comes at a surprise to you.
- throwaway894345 5y agoIf you're pushing the database up into the application layer, do you have to route all write operations through a single "master" application instance? If not, is there some multi-master scheme, and if so, is it cheaper to propagate state all the time than it is to have the application write to a master database instance over a network? Moreover, how does it affect the operations of your application? Are you still as comfortable bouncing an application instance as you would otherwise be?
- mrkurt 5y agoThe answer is: yes, you do have to write through a single primary application instance. So far. The two important things here are: 1. Fly.io makes it really easy to write through a single primary application instance 2. There are ways to solve this problem so your application doesn't have to worry about it. Right now, you have to be a little careful bouncing app instances. If you bounce the writer, you can't perform writes for 15s or whatever. This is a big problem during deploys. There are a tremendous number of Fly.io users that are fine with this limitation, though. It's pretty valuable for some segment of our customers right now.
- throwaway894345 5y agoIt definitely seems like it could be useful for some use cases; I'm just trying to get my head around the constraints. :)
- lucasyvas 5y agoWhat are some ways alluded to in number 2?
- funstuff007 5y agoThis is exactly the reason I am so skeptical of the cloud. I don't care how easy it is to stand up VMs, containers, k8s, etc. What I need to know is how hard is it to lug my data to my application and vice a versa. My feelings on this are so strong as I work mostly on database read-heavy applications.
- teleforce 5y agoLocal-first software is the future: [1]Local-First Software:You Own Your Data, in spite of the Cloud: https://martin.kleppmann.com/papers/local-first.pdf https://martin.kleppmann.com/papers/local-first.pdf
- a-dub 5y agoif you can tolerate eventual consistency and have the disk/ram on the application vms, then sure, keeping the data and the indices close to the code has the added benefit of keeping request latency down. downside of course is the complexity added in synchronization, which is what they're tackling here. personally i like the idea of per-tenant databases with something like this to scale out for each tenant. it encourages architectures that are more conducive for e2ee or procedures that allow for better guarantees around customer privacy than big central databases with a customer id column.
- mwcampbell 5y ago> personally i like the idea of per-tenant databases with something like this to scale out for each tenant. So do I. And that type of architecture has come up a few times now in this comment thread. Given that Fly has the lead developer of the Phoenix web framework on staff, maybe it would make sense for him to work on integrating this type of architecture, with Litestream-based replication and the ability to have different master regions for different tenants, into Phoenix.
- yawaramin 5y agoNot sure that would make sense. Phoenix uses the Erlang OTP platform, which ships with its own distributed database, Mnesia: https://www.erlang.org/doc/man/mnesia.html https://www.erlang.org/doc/man/mnesia.html
- tptacek 5y agoIn practice, Phoenix apps tend to be using Ecto and a mainstream database.
- mwcampbell 5y agoPhoenix apps don't typically use Mnesia; they use a relational database through Ecto [1]. [1]: https://github.com/elixir-ecto/ecto https://github.com/elixir-ecto/ecto
- errantmind 5y agoJust wait until (some) devs realize they don't even need sqlite, and can serialize their data directly to binary flat files with simple locking synchronization for backups. I'm half joking but I've witnessed many devs use databases when a binary file will do. I've done this personally for years for most of my 'fits-in-RAM', non-transactional, denormalized datasets, which is almost all of them. Better yet, use both if you have both types of data. The performance benefits are enormous and well worth the complexity tradeoff in my experience.
- kortex 5y agoThat seems exactly opposite to the growing trend of "sqlite-as-application-file-format". There's a lot of nice features you get "for free" doing this, primarily way better consistency, than you do rolling your own binary format. I don't want to have to deal with locks if at all possible. Binary works fine if each file is atomic, but that does not sound like the case you are advocating.
- errantmind 5y agoWho said anything about rolling your own? I'm talking about writing your data models directly to disk, the serialization and deserialization are done for you with a simple annotation. And in most applications you don't ever have to deal with locks as most applications don't need multiple threads writing and reading, that can be done with a single thread and a lockless queue that multiple threads write to. You would need a lock for making backups of the files themselves but this is trivial and takes the form of error handling. The OS itself handles the lock, you just need to handle the case where you can't open the file for writing. This approach is not all that rare, lightweight, and very useful for minimizing latency. Why would you ever use a database if you don't actually need the features? It is much simpler to immediately have access to all your data in your application's data models.
- sanderjd 5y agoWhat confuses me about this architecture I guess is: why have a SQL database at all? This sounds like a local cache. Which sure, of course those are super fast. But why does it need to be relational if all the data fits on the edge?
- zarzavat 5y agoYou get SQL and ACID. If you don't need those then you pay a performance price for having them. If you do need them, then you pay a price for not having them. The best solution depends on the unit economics of the problem you are trying to solve. If you have a small number of high value users, then these approaches are premature optimisation, just use Postgres. If your business model is ad eyeballs then squeezing every last drop begins to seem very attractive because you can multiply your profitability (potentially).
- Kinrany 5y agoYou usually want ACID, but with N+1 queries not being a problem you no longer need SQL. The database can now be a really low-level key-value store with your favorite query language on top.
- benbjohnson 5y agoLitestream author here. I wrote an embedded key/value database called BoltDB a while back and I experimented with using it for application development. It had its pros and cons. The pros were that it was crazy fast and a lot of data access is just basic iterators. Some of the biggest cons were having to implement indexes on my own and that my schema was tied to my application language. Migrations can be more difficult if everything is tied to structs in your app and it's also difficult to inspect your database since there's no CLI REPL.
- sanderjd 5y agoSo the answer to my question might be "because SQLite already does some stuff really well, like indexes and its CLI, and it just happens to be relational and use SQL as its query language, but that's not the important part". I buy that.
- kumarvvr 5y agoThroughput for a single service / app improves, but does it really scale? Across a cluster, you will have to have data replication and sync routines, that are a whole mess themselves. The latency is not reduced, it is shifted elsewhere.
- raxxorraxor 5y agoThe usual use case for a database is that it has multiple users in different places which would be difficult with SQLite. But for other use cases I don't see a problem. I don't know how it scales ad infinitum, but you can manage a lot of data with it and the usual SQL server has limits too. Could be a good choice even before you care about latency.
- iveqy 5y agoJust the latency is really important to me! I even built an ERP system that has a response time below 100 ms for all operations, it's a design goal. My thought is that if you can see consumer changes depending on latency (for example on amazon or google) it is equally important for internal tools. Employee time is expensive.
- deepstack 5y agoa few years back working on Java project. Used H2 instead of postgres, and included H2 db as in application memory access. It speed up quries tremendously. There is just no beating in application db.
- mekster 5y agoI want functions.