IRCNF

SQLite is the database the cloud didn't expect — and it's winning anyway

Share:
SQLite is the database the cloud didn't expect — and it's winning anyway

There are roughly 1 trillion active deployments of SQLite in the world. That number, from the SQLite project's own documentation, is not a marketing estimate — it is an architectural reality. Every iPhone ships with SQLite. Every Android device runs it. Firefox uses it to store history, bookmarks, and cookies. Chrome uses it for its database backend. Skype, Dropbox, iTunes, VLC, and the entire Adobe Creative Suite embed it. The United States Library of Congress recommends it as an archival format. SQLite is, by deployment count, the most widely used database engine in existence — and until recently, most developers thought of it as the thing that ships inside mobile apps, not as serious infrastructure.

That framing is now obsolete. In 2026, SQLite is running inside Cloudflare's global edge network, powering distributed applications through Turso's libSQL fork, and forming the foundation of a local-first application architecture that is attracting serious engineering attention. The database that spent thirty years being called "not for production" is quietly redefining what production means.

What SQLite actually is

SQLite is a C library — around 155,000 lines of it — that implements a full SQL database engine in a single file with zero external dependencies, no server process, and no configuration. A database is just a file on disk. Opening it requires no connection string, no authentication handshake, no running daemon to connect to. You link the library, open the file, and execute SQL. That is the entirety of the setup.

Despite its simplicity, SQLite is fully ACID-compliant. Writes are atomic; concurrent reads are supported through its WAL (Write-Ahead Log) mode; the on-disk format has been stable and fully backward-compatible since 2004. It supports full SQL-92 with most of SQL:1999, including window functions, CTEs, and JSON operators added in more recent versions. The project is maintained by a small team under public domain dedication — no license, no copyright, no contributor agreements.

Richard Hipp started it in 2000 for the US Navy's guided missile destroyer program, where the absence of a database administrator was a design constraint, not an oversight. That origin defines everything about SQLite: it was built for environments where you cannot afford a server, a DBA, or network connectivity. Those constraints, it turns out, describe the edge computing environment almost perfectly.

SQLite at the edge: Cloudflare D1, Turso, and LiteFS

Cloudflare D1, launched into general availability in 2023 and substantially expanded through 2024–2025, is SQLite running inside Cloudflare Workers across 300+ edge locations worldwide. When a Worker executes a D1 query, it is running against a SQLite file co-located at the edge node closest to the user. Reads are sub-millisecond. The database can scale to 10 GB per database with no provisioning — you create a D1 database in one CLI command and it is immediately available globally.

D1 solves the write problem through a primary-replica model: writes go to a primary location and are replicated asynchronously to all edge nodes. For read-heavy workloads — which describes most web applications — the latency advantage over a single-region PostgreSQL instance is substantial. Cloudflare reports D1 serving over 50 billion rows read per month across its customer base as of early 2026.

Turso, built on libSQL — an open-source fork of SQLite maintained by ChiselStrike — takes a different architectural approach. libSQL extends SQLite with native replication, server mode, and HTTP API support while remaining wire-compatible with standard SQLite files. Turso provides embedded replicas: your application runs a local SQLite replica that stays in sync with a central database, giving you zero-latency local reads and eventual consistency on writes. The model is explicitly designed for edge runtimes and serverless functions where the latency cost of a remote database call is prohibitive.

LiteFS, developed by Ben Johnson and now maintained under the Fly.io umbrella, takes a FUSE-based approach to SQLite replication. It intercepts filesystem writes at the OS level and replicates the SQLite write-ahead log to other nodes via a consensus layer. Applications require no code changes — LiteFS sits between the application and the filesystem, transparently synchronizing SQLite databases across a Fly.io cluster. Fly.io Volumes, the persistent storage layer for Fly apps, combined with LiteFS gives developers a distributed SQLite setup with automatic failover and replication across multiple regions.

SQLite-over-HTTP and the new access patterns

One of the more interesting developments in the SQLite ecosystem is the emergence of HTTP-based access layers that make it behave more like a traditional client-server database without giving up its embedded advantages. libSQL's server mode exposes a WebSocket and HTTP API that clients can connect to remotely — meaning a SQLite database running on a server can be queried from a browser, a mobile app, or a serverless function using standard HTTP semantics.

This matters because it unlocks SQLite for environments where embedding the library directly is not possible. A Next.js application deployed on Vercel cannot bundle a native SQLite library — but it can make HTTP requests to a Turso database and get SQL query results back as JSON. The developer experience is nearly identical to querying Postgres over a connection pool, but the underlying engine is SQLite, with all the operational simplicity that implies.

Bun, the JavaScript runtime that has been gaining traction as a faster Node.js alternative, ships with native SQLite support through its bun:sqlite module — no npm install required, no native module compilation, no node-gyp. const db = new Database("mydb.sqlite"); is the entire setup. The performance numbers Bun cites for its SQLite implementation — over 4 million reads per second on a laptop — reflect how fast a zero-network-overhead database can be when it is running in the same process as your application code.

Local-first architecture and the rise of CRDTs

The local-first movement in web application development is built on a specific claim: that the right architecture for most applications is one where the database lives on the client, reads are instantaneous because they hit local storage, and synchronization with a server happens in the background. The user experience is faster, offline capability is built in, and the server becomes a sync relay rather than a query bottleneck.

SQLite is the natural fit for this architecture because it runs everywhere — in the browser via WebAssembly (wa-sqlite, sql.js), in Electron apps natively, on mobile via the platform's built-in SQLite, and on edge nodes through D1 or Turso. The same SQL queries work across all of these environments against files that are fundamentally compatible with each other.

The hard problem in local-first architecture is conflict resolution: if two clients both write to a local SQLite replica while offline, how do you merge those writes when they reconnect? This is where CRDTs (Conflict-free Replicated Data Types) enter the picture. cr-sqlite, a SQLite extension developed by Matt Wonlaw at Vlcn.io, implements CRDT semantics directly in SQLite by instrumenting standard SQL tables with a Lamport clock and a merge function. Two cr-sqlite databases can be merged deterministically without a central authority. Any row-level conflict is resolved by the CRDT merge rules, not by a server deciding which write wins.

This combination — SQLite for storage, CRDTs for merge semantics, a sync relay for connectivity — is the architecture behind tools like ElectricSQL, Replicache, and Zero (from the Rocicorp team that built Replicache). It is no longer purely experimental: Linear, the project management tool, uses a local-first SQLite-based architecture for its desktop app, and attributes its snappy feel specifically to the fact that every interaction hits a local database rather than a remote API.

Developer tooling in 2026

The ORM and tooling ecosystem has caught up with SQLite's expanded role. Drizzle ORM, one of the fastest-growing TypeScript ORMs, treats SQLite as a first-class target alongside PostgreSQL and MySQL — with specific adapters for better-sqlite3, Bun's native SQLite, libSQL, D1, and Turso. Drizzle's type inference means your SQLite schema drives your TypeScript types with zero runtime overhead.

Prisma added D1 support in 2024 with its driver adapters model, allowing Prisma's query engine to run against Cloudflare D1 through the D1 HTTP API. The Prisma schema definition stays identical whether you are targeting Postgres or D1; only the client initialization changes. better-sqlite3, the Node.js SQLite binding by Joshua Wise, remains the go-to for synchronous, high-performance SQLite access in server-side Node.js — its synchronous API design is a deliberate choice, matching SQLite's own synchronous nature and avoiding the async overhead that plagues most database drivers.

Where SQLite genuinely falls short

SQLite's single-writer model is its most significant architectural constraint. Only one write transaction can execute at a time — even in WAL mode, which allows concurrent reads alongside a single writer, you cannot have two processes writing to the same SQLite database simultaneously without serialization. For applications with high concurrent write throughput — a leaderboard taking thousands of score updates per second, a messaging system with simultaneous writes from thousands of connected clients — SQLite's write model is a hard wall.

WAL mode helps significantly for read-heavy workloads with occasional writes: readers never block writers and writers never block readers. But WAL does not change the fundamental single-writer constraint. If your bottleneck is write concurrency, you need a database with a lock manager designed for it — PostgreSQL, MySQL, or a distributed system like CockroachDB.

There is also no built-in replication. Standard SQLite has no concept of primary/replica, no WAL shipping, no logical replication slots. Every replication solution in the ecosystem — LiteFS, Turso's embedded replicas, cr-sqlite — is a layer built on top of SQLite by third parties. This means replication setups carry more operational complexity than they appear: you are managing two systems (SQLite plus the replication layer) rather than one. And the consistency guarantees vary: Turso's embedded replicas are eventually consistent, not strongly consistent — a write on one replica may not be immediately visible on another.

Database file size also becomes a consideration at scale. SQLite handles databases in the tens of gigabytes routinely and has been tested to hundreds of gigabytes, but at that scale, you lose some of the operational simplicity that makes SQLite attractive. Moving a 50 GB SQLite file for backup purposes is a different proposition than replicating it via a log-based stream.

When to choose SQLite, and when not to

SQLite is the right choice when your read-to-write ratio is high, when you want zero operational overhead, when you are building for the edge or for local-first architectures, or when you are shipping a developer tool, CLI, or embedded application where a database server would be absurd. D1 and Turso have made it viable for production web applications with global users, provided those applications are read-heavy and can tolerate eventual consistency on writes.

PostgreSQL remains the right choice when you need strong write concurrency, row-level locking, complex replication topologies, or the deep extension ecosystem (PostGIS, pgvector, TimescaleDB) that Postgres has built over thirty years. MySQL and MariaDB occupy similar territory. A distributed database like CockroachDB or PlanetScale is warranted when you need horizontal write scaling with strong consistency guarantees across regions — a use case SQLite was never designed to address.

The more interesting question for 2026 is not "SQLite vs. Postgres" but "where does each belong in the same system?" Many production architectures are now using both: SQLite at the edge for user-specific, low-write data (session state, preferences, per-user feeds) and Postgres at the center for shared, high-write data (transactions, inventory, messaging). The database the cloud didn't expect has found its place in the stack — not by replacing what came before it, but by handling the cases where spinning up a Postgres cluster was always the wrong answer.

Share:
SQLite is the database the cloud didn't expect — and it's winning anyway | IRCNF - Intelligent Reliable Custom Next-gen Frameworks