The Default Stack is Too Heavy
For the last decade, if you ran rails new, you almost immediately swapped the default database for PostgreSQL. Then, you spun up a Redis instance for Sidekiq. Then, maybe Elasticsearch for search.
Before you wrote a single line of business logic, you were managing three separate services.
For a team of 10? Fine.
For the "One-Person Framework"? It’s technical debt.
With the release of Rails 8 and the advancements in modern storage hardware, the rules have changed. It is time to stop treating SQLite like a toy and start treating it like the production-grade powerhouse it is.
Here is why your next indie SaaS should run on a single file.
The Hardware Shift: NVMe Changed Everything
Why did we move away from file-based databases in the 2000s? Spinning hard drives.
Random I/O on a spinning disk was excruciatingly slow. Concurrent writes were a nightmare.
Today, your $5 VPS isn't running on a spinning disk. It’s running on NVMe SSDs.
These drives are insanely fast. We are talking about 3GB/s read speeds and hundreds of thousands of IOPS.
When your storage is this fast, the bottleneck isn't the disk anymore. The bottleneck is the network.
- Postgres: App -> TCP Connection -> Socket -> Postgres Process -> Disk -> Network -> App.
- SQLite: App -> Direct System Call -> Disk.
SQLite eliminates the "Network Tax." It runs inside your application process.
The Rails 8 "Solid" Revolution
Rails 8 has gone all-in on the "database-backed" architecture. The Rails team realized that managing Redis just for cache and jobs was a hurdle for solo devs.
They introduced the "Solid" trilogy, which allows SQLite to handle the duties of Redis:
- Solid Queue: Background jobs kept in a standard SQLite table. No Redis required.
- Solid Cache: Caching HTML fragments and data in a SQLite table. Because reads are so fast (no network latency), this is often faster than a networked Redis instance.
- Solid Cable: WebSocket pub/sub handling via the DB.
Suddenly, your infrastructure diagram collapses from a spiderweb of services into a single server with a single file.
But... "SQLite Can't Scale," Right?
This is the most common objection. "It doesn't handle concurrency!"
False.
By enabling WAL (Write-Ahead Logging) Mode, SQLite becomes significantly more capable of handling concurrent readers and writers.
# config/database.yml
production:
adapter: sqlite3
database: storage/production.sqlite3
timeout: 5000
pool: 5
# Enable WAL mode for better concurrency
pragmas:
journal_mode: wal
synchronous: normal
Unless you are building the next Twitter, you are unlikely to hit the write-lock limit of modern SQLite. We are talking about handling hundreds of requests per second on a modest VPS.
If you do hit that limit, congratulations! You have a successful business with enough revenue to pay someone to migrate you to Postgres. Don't optimize for a problem you don't have yet.
The "N+1" Superpower
We spend hours optimizing N+1 queries in Rails to avoid "chatty" network calls to Postgres.
- Request 1: 10ms
- Request 2: 10ms
- ...
In SQLite, an N+1 query is just a function call. It is startlingly fast. You can loop through 100 records and query associated data, and it might finish in 2ms total.
Moving to SQLite actually allows you to write simpler code because you don't have to fear the database trip as much.
What about Backups? (Crucial!)
"If the server dies, I lose my file."
This is solved by Litestream (or LiteFS).
Litestream runs as a sidecar process. It hooks into SQLite's WAL updates and streams them—in real-time—to Amazon S3 (or any object storage).
If your server catches fire, you can restore your database to the exact second it went down by pulling from S3. It is arguably easier to set up than a Postgres pg_dump cron job.
Summary: The One-Person Stack
The goal of the solo developer is velocity.
- No Docker containers to orchestrate.
- No connection pool errors.
- No Redis version mismatches.
- Just
rails server.
Complexity is the mind-killer. Simplify your stack, and you’ll find you have a lot more brainpower left over to actually build your product.
Are you brave enough to run SQLite in production? Let me know your thoughts below! 👇
Top comments (0)