SQLite vs Postgres vs MySQL: Which Database Should You Pick?
Compare SQLite, PostgreSQL, and MySQL by architecture, concurrency, feature depth, and use cases to pick the right database for your project.
SQLite vs Postgres vs MySQL: Which Database Should You Pick?
Choosing a relational database is one of the highest-leverage decisions in a project. SQLite, PostgreSQL, and MySQL are all mature, free, and widely deployed, but they solve very different problems. Below is a practical comparison across architecture, concurrency, feature depth, and use cases so you can pick the right one the first time.
Architecture at a Glance
SQLite is an embedded library, not a server. Your application links against SQLite and reads and writes a single .sqlite file directly. There is no daemon, no network socket, no user management. A production database can literally be copied with cp. This makes it the most widely deployed database on Earth: it ships in every phone, browser, and countless desktop apps.
PostgreSQL is a client-server database with a multi-process architecture (one backend process per connection, plus background workers). It implements a large portion of ANSI SQL, supports rich extensions (PostGIS, pgvector, TimescaleDB), and offers first-class JSON and binary JSONB types with GIN indexing. It is the default choice of modern managed platforms like Supabase, Neon, and RDS.
MySQL is also a client-server database, historically famous for LAMP-stack speed and simplicity. Modern MySQL (8.x) uses the InnoDB storage engine by default, which brings ACID transactions, row-level locking, and a native JSON type. It remains the backbone of massive workloads (WordPress, Shopify, Facebook's early stack) and is available everywhere.
Concurrency Model
This is where the three diverge most sharply.
- SQLite: allows many concurrent readers but only a single writer at a time. In WAL (Write-Ahead Logging) mode readers do not block writers, but two writers must serialize. That is fine for a phone app or a low-write web service, but it is a hard ceiling for write-heavy workloads.
- PostgreSQL: uses full MVCC (Multi-Version Concurrency Control). Every transaction sees a consistent snapshot, and readers never block writers. Writers only conflict when they touch the same row. This scales cleanly to thousands of concurrent connections (with a pooler like PgBouncer).
- MySQL (InnoDB): also uses MVCC with row-level locking. Concurrency is excellent in practice, though its isolation semantics (default
REPEATABLE READwith gap locks) differ from Postgres's defaultREAD COMMITTEDand can surprise you.
Feature Depth
As a rough ranking for advanced SQL and correctness: Postgres > MySQL > SQLite.
Postgres offers window functions, CTEs (including recursive and writable), full-text search, materialized views, table inheritance, generated columns, LATERAL joins, custom types, and an extension system that lets it host vector search, geospatial data, and time-series compression in-process. MySQL has caught up on window functions, CTEs, and JSON in 8.0, but its extension story, planner, and type system are noticeably narrower. SQLite supports a surprisingly modern subset (window functions, CTEs, JSON1, FTS5) but keeps types loose (dynamic typing by default) and omits many enterprise features.
Comparison Table
| Dimension | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| Deployment | Embedded file, no server | Client-server | Client-server |
| Concurrency | Single writer, many readers (WAL) | MVCC, no reader-writer blocking | MVCC + row-level locks (InnoDB) |
| SQL depth | Modern subset, dynamic types | Full ANSI SQL + extensions | Good, catching up in 8.x |
| JSON | JSON1 extension | JSON + indexed JSONB | Native JSON type |
| Replication | Litestream, LiteFS, Turso | Logical + streaming built-in | Async, semi-sync, group replication |
| Typical scale | GB to low TB, single node | TB+, HA clusters | TB+, HA clusters |
| Best fit | Embedded, edge, local-first | New production apps | Legacy or MySQL-ecosystem apps |
When to Pick Each One
Choose SQLite when
You are building a mobile or desktop app, a CLI tool, a browser extension, a test fixture, or an edge/local-first web app. Cloudflare D1, Turso, LiteFS, and Litestream have turned SQLite into a legitimate backend for many production sites: reads are microsecond-fast because the database lives in the same process, and replication/backup is now a solved problem. If you have low-to-moderate write volume and want radically simpler operations, SQLite is often the right answer.
Choose PostgreSQL when
You are starting a new production app and have no strong reason to pick something else. Postgres is the safe default in 2026: it scales, its type system prevents whole classes of bugs, its ecosystem (pgvector for AI, PostGIS for geo, logical replication for CDC) covers cases you have not thought of yet, and every major managed platform offers it. Pick Postgres when you want optionality: it grows with you.
Choose MySQL when
You are working inside the MySQL ecosystem: a legacy schema, WordPress/Magento/Shopware, a hosting environment that only offers MySQL, or a team with deep MySQL operational muscle memory. It is a great database, and PlanetScale/Vitess-style horizontal scaling is genuinely best-in-class. But for greenfield work without those constraints, Postgres usually wins on features and standards compliance.
Bottom Line
Think of the three as concentric use cases. SQLite handles anything that fits on one machine and does not need a server. MySQL handles multi-user production workloads where the ecosystem or history points to it. PostgreSQL handles almost everything else, and is the modern default when you are unsure. Match the tool to the constraint set you actually have, not to what is fashionable.