Answers · Deploying

Can I run SQLite in production for a Rails app?

Yes, for one server. Rails 8 ships SQLite configured for production use, and One Shot runs on it: the database is a file on a mounted volume, backups are a file copy, and there is no second service to operate. The limit is real though. Two application servers cannot write to the same SQLite file, so horizontal scaling is where it stops.

What makes it work now and did not before

Rails 8 sets the pragmas that used to be the reason people said no. Write-ahead logging lets readers continue while a write is in flight, and a busy timeout makes concurrent writers wait rather than raise. You can see the configuration in config/database.yml.

Solid Queue, Solid Cache and Solid Cable also use SQLite, which is why a One Shot deploy has no Redis and no separate job host. Four databases, four files, one container, declared together in config/database.yml and mounted by the volume line in config/deploy.yml.

bin/kamal app exec 'bin/rails runner "puts ActiveRecord::Base.connection.adapter_name"'

Where the limit actually sits

Not at a row count, and not at a request rate. It sits at the number of machines that need to write. One server handles a surprising amount of traffic, because a local file read has no network hop at all. The moment you want two application servers behind a load balancer, the file cannot be shared, and the answer is Postgres.

Watch for the signal rather than a number: sustained SQLite3::BusyException in the logs means writes are queueing longer than the busy timeout, and that is the point to move.

Back it up like a file, because it is one

bin/kamal app exec 'sqlite3 storage/production.sqlite3 ".backup /tmp/backup.sqlite3"'

Use .backup rather than copying the file directly. A plain cp of a database mid-write gives you a corrupt copy, and you will not find out until you try to restore it.

When to choose Postgres instead on day one

Three cases. You already know you need multiple application servers. You need an extension such as PostGIS or pgvector. Or your team has an operational preference and someone else runs the database. Outside those, starting on SQLite and moving later costs one migration, and most apps never do it.

Related questions

How do I back up a SQLite database on a live server?

Run sqlite3 storage/production.sqlite3 ".backup /tmp/out.sqlite3" inside the container, then copy the result off the host. The .backup command takes a consistent snapshot while writes continue; a plain cp of a live database gives you a file that looks fine and fails on restore. Store it somewhere the server cannot reach.

How do I deploy a Rails 8 app without Heroku?

Use Kamal, which ships with Rails 8. You give it a server over SSH and a container registry in config/deploy.yml, run kamal setup once, and kamal deploy after that. It builds an image, pushes it, and swaps containers with no downtime. A $5 VPS replaces the PaaS.

How do I deploy a Rails app from GitHub Actions?

Run kamal deploy as a workflow step. Kamal needs three things in the runner: an SSH key that can reach the server, registry credentials, and RAILS_MASTER_KEY. All three go in as repository secrets and are read by .kamal/secrets. Gate the deploy job behind the test job so a red build never ships.