As databases evolved, so too did the strategies we use to plug them in to our applications. Almost since Codd, we've divided those apps into tiers. First came the database tier. Later, with memcached and Redis, we got the caching tier. We've got background job tiers and we've got routing tiers and distribution tiers. The tutorials pretend that there are 3 tiers, but we all know it's called "n-tier" because nobody can predict how many tiers we're going to end up with.
If you're careful, using this kind of database can get you a lot of performance. But for general-purpose use, you don't want to run your database off the open headers like a funny car. I thought about the kind of work I'd have to do to make BoltDB viable for more applications, and the conclusion I quickly reached was: that's what SQLite is for.
The most important thing you should understand about Litestream is that it's just SQLite. Your application uses standard SQLite, with whatever your standard SQLite libraries are. We're not parsing your queries or proxying your transactions, or even adding a new library dependency. We're just taking advantage of the journaling and concurrency features SQLite already has, in a tool that runs alongside your application. For the most part, your code can be oblivious to Litestream's existence.
But database optimization has become less important for typical applications. If you have a 1 GB database, an NVMe disk can slurp the whole thing into memory in under a second. As much as I love tuning SQL queries, it's becoming a dying art for most application developers. Even poorly tuned queries can execute in under a second for ordinary databases.
There's a magic number for application latency: responses in 100ms or less feel instantaneous. Snappy applications make happy users. 100ms seems like a lot, but it's easy to carelessly chew it up. The 100ms threshold is so important that people pre-render their pages and post them on CDNs just to reduce latency.