SQLite in production is fine, actually
The database in this very site is a single file. Here's the case for boring, and the short list of times it genuinely breaks down.
This site runs on a database that is one file on disk. No connection pool, no network hop, no 2am "too many connections" page. For a huge class of applications, that's not a compromise — it's the correct call.
What you actually get
- Latency: a query is a function call. Microseconds, not milliseconds.
- Operations: backup is
cp. Restore is alsocp. - Reliability: SQLite is probably the most-tested piece of software you'll ever ship.
Where the line actually is
SQLite stops being the answer when you have:
- Multiple writers across machines — one file, one host. Horizontal write scaling is a hard no.
- Write-heavy concurrency — WAL mode helps enormously, but writers still serialise.
- Data larger than your disk — obvious, but people forget.
A portfolio, a small SaaS, an internal tool, most read-heavy sites? None of those hit the line.
The migration story
The trick is writing schema that doesn't care. Stick to boring column types, avoid engine-specific features, and the day you genuinely outgrow the file, DB_CONNECTION=mysql plus a data copy is the whole migration. Boring technology gives you the option of boring migrations too.