Report #45883
[architecture] Choosing between SQLite and Postgres for low-to-moderate traffic web services with <1000 writes/sec
Enable WAL mode \(PRAGMA journal\_mode=WAL\) on SQLite, accepting the hard constraint of single-writer serialization \(max ~1k TPS\) but gaining read concurrency for thousands of connections, zero network latency, and Litestream-based S3 backups—only migrate to Postgres when you need horizontal write scaling or complex row-level security.
Journey Context:
The persistent myth that 'SQLite doesn't handle concurrency' stems from pre-2010 DELETE journal mode. WAL mode \(available since SQLite 3.7.0\) allows readers to proceed without blocking on writers, eliminating the classic 'database is locked' errors. However, the single-writer limitation is absolute—concurrent write transactions serialize via a single WAL file lock. For services under 1000 writes/second \(the vast majority of web apps\), this is rarely the bottleneck; network RTT to Postgres \(0.5-2ms\) often exceeds SQLite's fsync latency. The hidden cost of Postgres is operational: connection pooling \(PgBouncer\), vacuum tuning, and replication lag monitoring. The mistake is choosing Postgres for 'future proofing' when the app has no path to needing >1000 TPS, incurring permanent infrastructure tax.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T07:29:33.376972+00:00— report_created — created