Postgres vs SQLite or Turso vs MySQL for a solo developer's web app
Postgres 18.6. One process gives you JSONB, full-text search, `LISTEN/NOTIFY`, and a job queue on `SELECT ... FOR UPDATE SKIP LOCKED`, so a solo app can go a long way before it needs a second service. SQLite 3.53.4 in the same container is faster and simpler when exactly one machine writes; the moment you want two app replicas, you are building replication yourself or paying Turso for it.
SQLite, embedded or through Turso, has no network hop and no connection pool. Turso's free plan is 100 databases, 5 GB, 500 million rows read and 10 million rows written per month.
Wins when one machine does all the writing, or you want a separate small database per tenant.
MySQL 8 is a fine database and a poor default here: you give up JSONB operators, partial and expression indexes are newer and narrower, and almost every Postgres-first tool in the TypeScript ecosystem treats it as the second target.
| severity | versions | symptom and fix |
|---|---|---|
| major | >=9.5.0 | Two app replicas both run migrations at boot and the second one fails on an already-applied step. Run migrations from one place, a release step or a jobs container, and wrap the run in `pg_advisory_lock(<constant>)` so a second process waits instead of racing. evidence |
VERDICT Postgres vs SQLite or Turso vs MySQL for a solo developer's web app PICK PostgreSQL 18.6: Postgres 18.6. One process gives you JSONB, full-text search, `LISTEN/NOTIFY`, and a job queue on `SELECT ... FOR UPDATE SKIP LOCKED`, so a solo app can go a long way before it needs a second service. SQLite 3.53.4 in the same container is faster and simpler when exactly one machine writes; the moment you want two app replicas, you are building replication yourself or paying Turso for it. ALT SQLite: SQLite, embedded or through Turso, has no network hop and no connection pool. Turso's free plan is 100 databases, 5 GB, 500 million rows read and 10 million rows written per month.; wins when one machine does all the writing, or you want a separate small database per tenant AVOID MySQL: MySQL 8 is a fine database and a poor default here: you give up JSONB operators, partial and expression indexes are newer and narrower, and almost every Postgres-first tool in the TypeScript ecosystem treats it as the second target. TRAPS (1) [1163f1d7] major: Two app replicas both run migrations at boot and the second one fails on an already-applied step. VERIFIED 2026-09-08 by wellworn reviewer · recheck 2027-01-06 · sources 4