How much does your choice of database actually matter?
Everyone online has a strong opinion. That Postgres is the best database ever and the only thing you should ever use. I disagree and to prove my point, I tested 4 of them with an actual production workload.
The contenders: Postgres, MySQL, MariaDB, and SQLite.
(This isn't SQL vs NoSQL. It's just which SQL database gets the most out of a small server.)
Technical Spec / Setup
I used a $12 DigitalOcean server with 1 shared CPU, 2 GB of RAM, and 50 GB of SSD. On it runs a simple social media API written in Go. You can load your feed, open posts, like things, and create posts.

Important detail: the app and database run on the exact same machine. There is no dedicated database server.
Every database started with the exact same data: 50,000 users, 500,000 posts, and a little over 2 million likes. I generated it once, loaded the exact same files into each database, and verified they were identical byte for byte.
Then I used k6 on a separate server to throw virtual users at it. Each user loads the feed, waits a few seconds, opens a post, maybe likes something, maybe writes a post, and repeats. In this first workload only about 8% of requests write to the database.

To pass, a database had to survive 5 straight minutes with p95 latency under 500ms, p99 under 1 second, and under 1% errors.
The only tuning I did was give the database 512 MB of memory for its cache. Everything else stayed at the defaults.
Round 1: Postgres
Everyone's favorite database right now. It topped out at 6,350 simultaneous users, around 600 requests per second. At that point Postgres was eating 58% of the CPU, and the Go API only got 23%.
Round 2: MySQL
I swapped Postgres for MySQL and kept the app, data, and SQL identical. MySQL passed at 6,650 users, barely ahead of Postgres. If these were the only two databases I tested, this would be a pretty boring email. They landed within about 5% of each other.
Round 3: MariaDB
This is where it got interesting. MariaDB is a fork of MySQL, and the app was literally using the same MySQL driver and Go binary. It destroyed MySQL, It topped out at 9,300 users, about 40% more than MySQL on the exact same server.
So I compared them side by side at the same 2,000-user load. MariaDB used 24–29% less CPU per request. The bigger shock was disk writes: MariaDB wrote 9–14x less data for the exact same work (56 KB/s vs 701 KB/s).
I didn't isolate the exact cause, but a few default differences could explain it. MySQL 8 turns on performance_schema by default and MariaDB doesn't, and their default I/O behavior differs.
Round 4: SQLite
SQLite works differently from the other three. Postgres, MySQL, and MariaDB each run a separate server process. Your app sends a query over a connection, the database does the work, and it sends results back.
SQLite has no server. It's a library embedded directly in your app, and the database is basically a file on disk.

So I expected it to do well here, and it did. It passed at 13,400 users, roughly double Postgres. The CPU numbers explain why. With no database process hogging the CPU, about 70% of it went to the Go app, SQLite work included.
On raw feed reads, SQLite did ~1,850 requests/sec. MariaDB did ~1,000, MySQL 958, and Postgres ~550.
So is SQLite the best database? Not quite.
Your ad here
Want your project or service in front of 20,000 developers? Reply to this email and let's talk about getting you into the next edition.
Plot twist: heavy writes
The first workload is realistic for a social app: mostly reads. But plenty of apps aren't like that. A logging system writes constantly and barely reads.
So I cranked up the writes. Now every user likes posts and half of them create posts, taking us from 8% writes to 43%.
That completely changed the bottleneck. Before, the server was limited by CPU. Now it was spending its time waiting on the disk.
Postgres: 6,350 → 3,850
MySQL: 6,650 → 3,150
MariaDB: 9,300 → 5,000
SQLite: 13,400 → 6,800
SQLite still won, but it kind of cheated.
My default SQLite setup used WAL mode with synchronous=NORMAL. That's a common production config, and your commits survive an app crash. But if the whole machine loses power, you could lose your most recent commits.
Postgres, MySQL, and MariaDB were all flushing to disk on every commit. So it was an unfair comparison.
I re-ran SQLite with synchronous=FULL, the same guarantee as the others. And it nuked SQLite's performance.
On the realistic workload it still handled 10,000 users, which is very impressive. On the write-heavy workload it collapsed to 1,550, the worst of any database. The server spent almost 40% of its time just waiting on the disk.
This is one of SQLite's fundamental trade-offs. It only allows one writer at a time, and with full durability, that writer waits on a disk flush for every single commit. Server databases use group commit, where many transactions share one flush to disk. With lots of concurrent durable writes, that architecture matters a lot.

What about more data?
Maybe the database was just too small to matter. So I multiplied the data by 10: 500,000 users, 5 million posts, and 20 million likes, about 1.6 GB of raw data.
The results barely changed. SQLite passed at 14,500, MariaDB at 8,000, MySQL at 6,050, and Postgres at 5,150. Size still matters eventually, but going from ~155 MB to 1.6 GB didn't cause any big collapse.
Full results
Max simultaneous users each database held for 5 minutes with 0% errors:
Database | 1x realistic | 1x write-heavy | 10x realistic | 10x write-heavy |
|---|---|---|---|---|
SQLite | 13,400 | 6,800 | 14,500 | 7,300 |
MariaDB | 9,300 | 5,000 | 8,000 | 4,400 |
MySQL | 6,650 | 3,150 | 6,050 | 3,000 |
Postgres | 6,350 | 3,850 | 5,150 | 4,050 |
SQLite (FULL sync) | 10,000 | 1,550 | - | - |
So what does this actually mean?
SQLite looks amazing here, but there's a really important caveat: this entire test ran on one server. The app and database lived on the same machine, which plays right into SQLite's biggest strength. With no separate database process, a lot of overhead disappears.
So if you want to squeeze as much as possible out of one machine running both your app and database, SQLite is a very good choice a lot of the time.
But Postgres, MySQL, and MariaDB solve a different problem. They're built to be database servers, and that matters once your app needs more than one machine. Postgres can replicate to standby servers and fail over if the primary dies. MySQL has replication, InnoDB Cluster, and group replication. MariaDB has replication and Galera Cluster.
All that machinery adds overhead that doesn't help in a benchmark on one tiny server. In a real production environment, it's probably what you want.
So be careful taking away "SQLite is the best database" or "MariaDB beats Postgres." For a small API on one server, this is where you get the most performance.
And on a $12 server, every single one of these handled thousands of simultaneous users. Your database is probably not why your side project isn't scaling.
Check my configs
I published the exact database configs I used, so you can check them or tell me what I got wrong:
Have a good week!
Arjay.
P.S. If you want to chat with me directly or get advice on this stuff, the best way is through my private discord server included with Devmaxx. Try it free for 7 days at devmaxx.dev.