SQLite Is Eating the World

The Most Deployed Database You've Never Deployed
SQLite is installed on over one trillion devices. Your phone has it. Your browser has it. Every macOS installation ships with it. It powers the SMS database on Android, bookmark storage in Firefox, and the photo metadata on your iPhone. And yet, until recently, most backend developers treated it as a toy — something for prototypes, mobile apps, and local scripts, not for running a real web service.
That's changing fast.
What SQLite Actually Is
SQLite isn't a database server. It has no network layer, no authentication system, no daemon to manage. It's a C library that reads and writes a single file on disk. You link it into your application and call it directly — no connection strings, no port numbers, no configuration files to manage.
What it does have: full ACID compliance, a complete SQL implementation (window functions, CTEs, JSON support, full-text search), sub-millisecond query performance for typical workloads, and a file format so stable that the SQLite team guarantees backward compatibility until 2050. The entire database is one file you can copy, email, or put in version control.
For 30 years, that combination made it the dominant database for embedded use cases — the kind where you need persistence without infrastructure. But "embedded" is being redefined.
Why Production Use Wasn't Obvious
The traditional knock on SQLite for server workloads comes down to two real limitations:
- Concurrency: SQLite uses file-level locking. In WAL mode (
WAL= Write-Ahead Log), readers don't block writers and vice versa, but you still get one writer at a time. High-concurrency write workloads will queue up. - Single machine: The database lives on a filesystem. No built-in replication, no standby failover, no multi-region writes. If your server dies, so does your database.
These are real constraints. But for most web applications, they're irrelevant. The average CRUD app has a read/write ratio that's 90% reads. Write concurrency beyond a few dozen requests per second is a problem most apps will never have. The complexity of Postgres — connection pooling, replication lag, standby failover, schema migrations across replicas — exists to solve problems that don't exist at the scale most developers are actually operating at.
The Distributed SQLite Wave
The ecosystem that's emerged around SQLite for server use has directly addressed the remaining limitations. Three projects are driving the shift.
Turso and LibSQL
LibSQL is an open-source fork of SQLite maintained by Turso. It adds the features that made SQLite impractical for server deployments: WAL-mode replication over HTTP, remote access over a native protocol, loadable extensions enabled by default, and embedded replica support — meaning your application can keep a local SQLite copy that syncs from a remote primary. You get local read latency with remote durability.
The result is something that feels like a serverless database but performs like a local file. Turso's hosted service lets you spin up databases in seconds and replicate them across regions without touching a config file. Their free tier is generous enough that small apps never pay a dollar.
Cloudflare D1
Cloudflare D1 runs SQLite inside Cloudflare Workers at the edge. When a Worker in Frankfurt queries D1, it's hitting a SQLite instance running in the same data center, not crossing an ocean to reach a Postgres cluster in Virginia. Query latency that was measured in hundreds of milliseconds drops to single digits.
D1 handles replication transparently. You write to a primary, Cloudflare replicates reads to edge locations. The API is standard SQL — you can use drizzle-orm, kysely, or raw queries. It's SQLite with a global read layer that you didn't have to build.
Bun's Built-In SQLite
Bun ships with a native SQLite binding as of v1.1 — no npm install, no native module compilation, no better-sqlite3 dependency to manage. You import bun:sqlite and open a database. That's it. For JavaScript developers building lightweight services or CLI tools, the friction of adopting SQLite just dropped to zero.
Rails 8 Made It the Default
The most important signal that SQLite has crossed a threshold: Rails 8, released in late 2024, ships SQLite as the default database for new applications. This isn't a prototype convenience — DHH and the Rails core team have been explicit that SQLite is the right choice for most applications, and they've invested in tooling to make it production-ready: solid_queue for background jobs on SQLite, solid_cache for caching, and Litestream-based backup integration.
When the framework that defined the modern web application pattern defaults to a file-based database, the industry conversation has shifted.
The "SQLite for Everything" Argument
The argument isn't subtle: for 80% of web applications, you don't need Postgres. You don't need a connection pool. You don't need a replica. You need a database that's fast, reliable, and doesn't require a systems administrator to operate.
SQLite gives you:
- Zero configuration — no server to start, no user to create, no port to open
- Instant setup — create a file, start writing SQL
- Trivial backups — copy the file, or use Litestream for continuous replication to S3
- Excellent read performance — sub-millisecond for indexed queries on databases up to tens of gigabytes
- ACID guarantees —
WALmode gives you concurrent reads and crash safety without tuning
The operational simplicity compounds. When your database is a file, your deployment is simpler. Your development environment matches production exactly. Debugging is easier. You can open the database in DB Browser for SQLite and look at the data directly.
Where It Still Doesn't Fit
SQLite won't replace Postgres everywhere. Multi-region write scenarios — where you need low-latency writes from multiple geographic locations simultaneously — are genuinely hard with SQLite. You can work around it with LibSQL embedded replicas and careful write routing, but it's not native. High-concurrency write workloads (think: a social feed with millions of simultaneous writers) will hit the single-writer bottleneck.
The Postgres ecosystem is also deeper: better extensions (pgvector, PostGIS, TimescaleDB), more mature observability tooling, decades of operational knowledge, and multi-version concurrency control that handles write contention more gracefully. If you're building a system where write throughput is the bottleneck, Postgres is still the right call.
The Shift Is Real
The pattern here isn't new. SQLite went from "toy" to "serious option" by solving the problems that kept it in the embedded world — and it did so not by becoming more complex, but by inspiring an ecosystem that added the missing pieces around it. LibSQL added replication. D1 added the edge layer. Litestream added continuous backup. Bun removed the install friction.
The result is a database engine that's been production-proven on a trillion devices, requires no infrastructure to run, and now has credible answers for the two objections that used to disqualify it. The question isn't whether SQLite can handle your app — it's whether your app actually needs what Postgres provides.
For most apps, the honest answer is no.