SQLite vs MySQL: Which to Use? (2026)
SQLite vs MySQL for founders — an embedded file-based database vs a client-server one, when SQLite is genuinely enough, and why Postgres is still the default.
Table of contents8 sections
- 01The Database That Was Already on My Laptop
- 02SQLite Is a File. MySQL Is a Server. Everything Follows From That.
- 03The Single-Writer Thing Everyone Panics About
- 04MySQL: The Database for a Room Full of People
- 05When SQLite Is Genuinely Enough
- 06The 2026 Twist: SQLite Grew Up in Public
- 07So Which One Should You Actually Use
- 08The Bottom Line
The Database That Was Already on My Laptop
Somewhere in the Clickly years — 2023, the URL shortener I over-engineered into the ground — I had a night where I got genuinely angry at myself.
I’d spent weeks chasing exotic databases to serve click analytics cheaply. ClickHouse, Timescale, columnar files, the whole advanced database rabbit hole. And that night I was reading about someone serving a read-heavy app to real traffic using nothing but SQLite — a single file sitting on the same box as the app. No database server. No connection string. No monthly bill. Just a .db file the app opened directly.
I’d had SQLite installed on my machine the entire time. It ships inside every phone, every browser, every Mac — probably the most-deployed database on the planet. And I’d mentally filed it under “toy, fine for tests, not for production,” the way most of us do, right up until I actually read how it works.
So when people search “SQLite vs MySQL,” I get it. They sound like two entries on the same list, two relational databases you’d pick between the way you pick MySQL vs Postgres. But they’re barely the same kind of thing. One is a library your code links against; the other is a server your code phones over a network. Understand that one difference and the comparison stops being a coin flip and becomes an architecture decision. (Fuzzy on how the language relates to any of these? Start with SQL vs MySQL.)
SQLite Is a File. MySQL Is a Server. Everything Follows From That.
Here’s the split, and it really is the whole post.
SQLite is embedded. It runs inside your application process. You don’t start a SQLite “server” because there isn’t one — it’s a C library your code calls directly, and your data lives in one ordinary file on disk. A query is a function call, not a network round-trip. There’s nothing to deploy, nothing to secure a port for, nothing to pay for. When your app shuts down, so does the database, because they were never separate things.
MySQL is client-server. It’s a long-running daemon that sits somewhere — its own box, a container, a managed host — and listens on a port (3306, if you care). Your app is a client that opens a connection, sends SQL over TCP, and gets rows back. That process runs whether your app is up or not. It has users, passwords, network access rules, and a bill.
That architectural gap explains every practical difference you’ll ever hit:
- Setup. SQLite:
import sqlite3, open a file, done. MySQL: provision a server, configure users, manage a connection pool, keep it patched. - Concurrency. More on this below, but a network server is built to juggle hundreds of simultaneous clients. A file is not.
- Where it can live. SQLite goes wherever your code goes — a laptop, a Lambda, a phone, an edge node. MySQL lives at a fixed network address everything dials into.
- Cost. A file costs nothing to run. A server is a machine somebody rents 24/7.
None of this makes one “better.” It makes them suited to different shapes of problem. A single-player mobile app has no business running a MySQL server. A fifty-person team hammering the same tables all day has no business sharing one SQLite file.
The Single-Writer Thing Everyone Panics About
The reason SQLite got its unfair “not for production” reputation is one real limitation: it allows exactly one writer at a time.
In the old default (rollback journal) mode, a write locked the entire database file, and readers had to wait too. That’s where the horror stories come from — a second write attempt bounces back with SQLITE_BUSY, and if you naively point a busy multi-user web app at it, you’ll see those errors constantly.
Then WAL mode changed the conversation. With Write-Ahead Logging turned on (one pragma), SQLite supports unlimited readers and one writer, concurrently. The writer appends new pages to a separate -wal file instead of locking the main one, so readers keep reading old-but-consistent data while a write is in flight — real snapshot isolation. Reads never block writes, writes never block reads. Only writes block other writes, and each write is measured in microseconds because there’s no network hop.
So the honest framing is this: SQLite’s ceiling isn’t “one user,” it’s “one write transaction at any given instant.” For an enormous number of apps that’s a non-issue — a read-heavy dashboard, a content site, a per-user app where each user only writes their own small database. It’s when many different users write to the same database at genuinely the same moment that the single-writer model turns into a queue, and a queue turns into latency.
MySQL, being a server, was designed for exactly that crowd. It does row-level locking and MVCC through its InnoDB engine, so hundreds of clients can write to different rows of the same table at once without stepping on each other. That’s not SQLite being bad — it’s a server doing the one thing a file fundamentally can’t.
SQLite doesn’t fail at concurrency. It just has a different, narrower definition of it — and for more apps than you’d think, that definition is plenty.
MySQL: The Database for a Room Full of People
Let me give MySQL its due, because it earned it.
MySQL is a client-server relational database owned by Oracle (it landed there in 2009 when Oracle bought Sun), with 8.4 as the current long-term-support line. It powers a staggering slice of the internet — the classic LAMP-stack web app, WordPress’s entire universe, a generation of startups. Its hard-won superpower is battle-tested horizontal scaling: YouTube’s engineers built Vitess to shard MySQL across many machines, then left and founded PlanetScale around it.
When many users write concurrently to shared data — a marketplace, a social app, a multi-tenant SaaS where everyone touches the same tables — you want a server: connection pooling, row-level locks, replication, and a thing that stays reachable no matter what your app process is doing. That’s MySQL’s home turf, and it’s very good at it.
The catch is everything that comes with running a server. It has to live somewhere online 24/7. Its flagship managed home, PlanetScale, killed its free tier back in 2024 — the cheapest way in now is a single-node database at $5/month, with production HA clusters starting around $15. When you have $0 MRR, “$5/month, forever” is a real line on a bill that a file simply doesn’t have.
When SQLite Is Genuinely Enough
Here’s the part I wish someone had told 2023-me before I went shopping for exotic engines. SQLite isn’t a compromise you settle for — for the right shape of app, it’s the better choice. Reach for it when:
- Reads massively outnumber writes. Blogs, docs sites, dashboards, catalogs, anything content-heavy. The single-writer limit never gets touched, and reads are absurdly fast because there’s no network.
- Each user (or tenant) writes only their own data. Give every user their own SQLite file and there’s no write contention between users at all — you’ve sidestepped the whole limitation by design. This is the per-user isolation pattern, and it’s beautiful for multi-tenant apps and AI agents.
- You’re at the edge. If your app runs on edge nodes close to users, a database file that ships alongside the code beats a central server every user has to round-trip to.
- It’s a single-box app or an internal tool. A lot of real, revenue-generating software is one server and a few hundred users. SQLite handles that without blinking, and you delete an entire piece of infrastructure from your life.
What SQLite is not for: a typical multi-user SaaS where lots of people write to shared tables concurrently, or anything you plan to scale horizontally across many app servers all needing to write. That’s server territory — and even then, my server of choice isn’t MySQL.
The 2026 Twist: SQLite Grew Up in Public
The reason this comparison is more interesting in 2026 than it was five years ago is that a small industry grew up around making SQLite work like a real, distributed, production database — without giving up the “it’s just a file” magic.
Turso is the big one. They took SQLite server-side: libSQL, their open fork, is the production-ready path, giving you isolated databases per user or per project at the edge. Their free tier is genuinely wild — 5 GB, up to 100 databases, 500 million row reads a month, for $0, with the Developer plan starting at $4.99/month when you outgrow it. That per-user-database pattern is exactly what a lot of AI-coding companies lean on. Turso is also rewriting SQLite from scratch in Rust (the project formerly codenamed Limbo), adding MVCC so it can do concurrent writes — that piece is still beta, but it tells you where this is heading: straight at the single-writer limitation itself.
Cloudflare D1 is SQLite living inside Cloudflare’s Workers world — great if you already build there, gravity you shouldn’t fight if you don’t. And Litestream solves the other historical fear (“a file? what about backups?”) by streaming every change to S3-compatible storage continuously, with point-in-time recovery — Fly.io relies on it for chunks of their own API.
None of this existed in usable form when I first dismissed SQLite. Today, “SQLite in production” is a defensible sentence — I dug into Turso and the whole per-user-database idea in the advanced database guide, and Bunny is quietly building a SQLite service on Turso’s tech too (the whole Bunny story).
So Which One Should You Actually Use
Let me be blunt, because I hate posts that won’t commit:
Use SQLite when your app is a file-shaped problem: read-heavy, single-box, edge-deployed, or one-database-per-user. It’s underrated, it’s free, it deletes infrastructure from your life, and in 2026 the tooling around it (Turso, Litestream) makes it a serious production choice, not a toy. If I were building a per-user or edge tool today, I’d start here and feel smart about it.
Use MySQL when you genuinely need a server for a crowd of concurrent writers and you’re inheriting a MySQL codebase, your platform is MySQL-native, or you can prove you need Vitess-grade sharding. Those are real cases. They’re just not most cases.
And here’s the verdict that ties this whole database series together: for a typical multi-user SaaS — the messy middle where most of us live — I still reach for neither. I reach for PostgreSQL on Neon (now a Databricks company): a real client-server database for concurrent users, better JSON and extensions than MySQL, no single corporate owner, and a free tier that scales to zero so a quiet database costs nothing. I’ve run seven Postgres databases on Neon for $0 for years. (The full MySQL-vs-Postgres head-to-head is right here; the menu of free database options is the shortcut.)
So the real hierarchy in my head isn’t “SQLite vs MySQL” at all. It’s: is this a file-shaped problem? If yes, SQLite (increasingly via Turso). If no — if it’s a normal multi-user SaaS — a Postgres server on Neon, and MySQL only when something specific forces my hand.
The Bottom Line
SQLite and MySQL aren’t really rivals. SQLite is an embedded, serverless database that lives inside your app as a single file — no server, no port, no bill, and shockingly capable for read-heavy, edge, and per-user workloads. MySQL is a client-server database built for a room full of people writing at once, and it’s excellent at exactly that.
The mistake I made in 2023 was assuming SQLite was beneath a “real” product. It wasn’t; I just didn’t understand what it was for. Figure out which shape your app is first. Then, for the messy multi-user middle where most SaaS lives, do the boring thing and run Postgres on Neon — and let SQLite quietly impress you everywhere it actually belongs.
This is the Broken Engineer Guide — I over-engineer everything, fail at business, and hand you the plain-English version so you skip the scars. Now go build something, and let it run off a file if it can.
