Production Database and Storage
Running SQLite in production, the storage volume, and S3-compatible file storage.
One Shot runs SQLite in production, not just in development. That's a deliberate choice for a kit meant to run on a single small server, not a limitation you're expected to migrate away from the moment you launch.
SQLite in production
Rails 8's SQLite adapter is production-ready, and it's what backs the database along with Solid
Queue, Solid Cache, and Solid Cable, none of which need a separate Redis or Postgres service. The
database files live in a Docker volume Kamal manages (oneshot_storage in this kit's own
deployment), which persists across deploys since the container itself is disposable but the volume
isn't.
Back this volume up, off the server, on a schedule. It's the one piece of state a redeploy can't recreate: your entire database and any locally stored uploaded files live inside it. A server failure without an off-server backup means losing everything in that volume, not just the running container.
When SQLite stops being enough
SQLite in this configuration comfortably handles the traffic most single-server apps see. If you outgrow a single server's disk and CPU for the database specifically, the standard path is moving to a managed Postgres instance and swapping the adapter, which is a deliberate, plannable migration rather than something you need to anticipate on day one. Most apps built on this kit won't hit that ceiling before other constraints do.
File storage: local disk versus S3
Active Storage, by default, writes uploaded files to local disk inside the same volume as the database. That works, and it's the zero-configuration default. For production, configuring S3-compatible object storage is worth doing before you have real user uploads to migrate:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,S3_BUCKET,S3_REGIONS3_ENDPOINT, if you're using an S3-compatible provider other than AWS itself (Cloudflare R2 and similar services work through this same configuration)
See Optional Integrations for where these are set. Until you configure them, the local-disk volume is the fallback, and it works correctly; it just means files live and get backed up alongside your database rather than in dedicated object storage.
Migrations
Run a one-off migration against the running production container directly through Kamal:
bin/kamal app exec "bin/rails db:migrate"
Next
You've now covered the whole deployment picture. See what every environment variable in the app actually does: Bring Your Own Keys.