Ruby & Rails

Ruby on Rails 8: The No-PaaS Release

Solid Queue, Solid Cache, Solid Cable and Kamal 2. Rails 8 removed the reasons most teams reached for a PaaS and a pile of infrastructure. What it means in practice.

A container deploying onto a single server running an integrated queue, cache and cable

The short version

  • The Solid trio moves background jobs, caching and WebSockets into your existing database, removing Redis from the default stack.
  • Kamal 2 deploys containers to any Linux server you can SSH to, with zero-downtime rollovers and automatic TLS.
  • The premise is that modern hardware and SQLite’s maturity make single-server deployments viable much further up the scale than assumed.
  • It is a genuine reduction in moving parts. It is not free — you take on the operations a PaaS was doing for you.

If Rails 7 argued you did not need a SPA, Rails 8 argues you do not need the infrastructure either. Released on 7 November 2024, its central claim is that the pile of managed services a typical Rails application depends on — Redis for jobs, Redis for cache, a separate service for WebSockets, a PaaS to tie it together — is largely avoidable.

The claim is stronger than it sounds and more conditional than the announcement suggested. Here is what actually shipped and when it applies.

The Solid trio

Three defaults that replace Redis with your relational database.

Solid Queue

A database-backed Active Job backend, now the default. It supports the things production job systems need: concurrency controls, recurring jobs, priorities, retries with backoff, and bulk enqueuing.

The advantage beyond removing a dependency is transactional integrity. When enqueuing writes to the same database as your business data, a job cannot be enqueued for a record whose transaction rolled back. That entire class of bug — the job that runs before the record is committed, or for a record that no longer exists — disappears.

Solid Cache

A database-backed cache store using disk rather than RAM. That sounds like a downgrade until you consider the economics: disk is orders of magnitude cheaper than memory, so a disk-backed cache can be enormously larger. A cache with a very high hit rate on slightly slower storage frequently beats a small cache with a poor hit rate on fast storage.

The honest caveat is that per-operation latency is higher than Redis. For caching rendered fragments and query results this is unimportant. For a hot counter incremented on every request, it is not.

Solid Cable

An Action Cable adapter using the database for pub/sub instead of Redis. It polls, which is less elegant than Redis pub/sub and entirely adequate at the message volumes most applications actually produce.

Watch your database load. Moving three workloads into the database means the database now carries three more workloads. Rails 8 encourages separate databases for each, which keeps job churn from competing with your application queries. Use that. Pointing all three at your primary database and then wondering why write latency climbed is a self-inflicted incident.

Kamal 2

Kamal deploys Docker containers to servers you control over SSH. No Kubernetes, no PaaS, no control plane. You describe your servers in a YAML file and run kamal deploy.

Version 2 added the pieces that made it genuinely usable rather than merely interesting:

  • Kamal Proxy replaced Traefik, with automatic Let’s Encrypt certificates and zero-downtime rollovers built in.
  • Multiple applications per host, so small services do not each need their own server.
  • Simpler configuration and considerably better defaults.

What you get is a deployment story that works identically on a cloud VM, a bare-metal box or a machine under a desk, at the cost of being responsible for the operating system, security patching, monitoring and backups. Whether that trade is good depends entirely on whether anyone on your team wants that job.

Authentication generator

Rails 8 ships rails generate authentication, producing session-based authentication with password reset, into your own codebase. This is not a gem and not a dependency — it is code you own and edit.

That framing is the right one. Authentication is close enough to every application’s specific requirements that a configurable gem tends to be fought with, and it is standard enough that writing it from scratch is wasteful. A generator that produces a correct starting point you then own resolves both.

SQLite in production

Rails 8 tuned its SQLite defaults for production: WAL mode, a sensible busy timeout, and configuration that avoids the failure modes that gave SQLite its reputation as a development-only database.

The case is stronger than instinct suggests. SQLite has no network hop, so reads are extraordinarily fast. It handles high read concurrency well. Modern hardware means a single server has resources that would have been a small cluster a decade ago.

The limits are equally clear. Writes are serialised, so write-heavy workloads will hit a wall. Horizontal scaling is not available. And replication and failover need external tooling such as Litestream rather than being built in.

Our reading: excellent for read-heavy applications, internal tools, and products that genuinely will not exceed one server. Postgres remains the default recommendation for anything where you are uncertain, and uncertainty is the normal state at the start of a product.

Does the argument hold?

Partly, and the part that holds is the important one.

What is genuinely true: most applications are dramatically over-provisioned. A single well-specified server handles far more traffic than teams assume, and the complexity of a distributed setup is frequently paid for capacity nobody will use. Removing Redis from the default stack removes a real operational burden for a real majority of applications.

What the announcement understated: a PaaS is not only providing infrastructure. It is providing operations — patching, monitoring, backup verification, on-call response. Kamal moves the deployment; it does not move the pager. For a team with no operations capacity, paying a PaaS may still be the cheaper option once you price the engineering time honestly.

The savings are real and they are denominated in infrastructure cost. The new expense is denominated in attention, and attention is the scarcer currency for a small team.

Should you adopt it?

A reasonable decision path:

  • New application, small team. Yes to the Solid trio; it is the default and it is simpler. Take Kamal only if someone will genuinely own the servers.
  • Existing application on Redis that works. There is no urgency. Migrate Solid Cache first if you want to try one, because it is the lowest-risk of the three.
  • Existing application on a PaaS. Compare the monthly bill against the honest cost of someone maintaining servers. Below a certain size the PaaS wins on total cost.
  • Write-heavy or genuinely large. Keep Postgres, keep Redis for hot paths, and take the parts of Rails 8 that suit you. None of this is all-or-nothing.

Boolean Solutions experience with Rails 8

We have been running the Solid stack on Kamal since the release candidates, and we are upgrading other applications to Rails 8 while deliberately keeping Redis. Both are correct in the right circumstances, and the deciding factor has consistently been operational capacity rather than anything technical.

The reduction in moving parts is real and worth having. Just be honest about what you are taking on in exchange. If you want help thinking that through for your setup, get in touch.

Further reading

  • Rails 8: No PaaS Required — the release announcement making the argument in its own words
  • Kamal — documentation for the deployment tool
  • Solid Queue — the job backend, including its concurrency controls
  • Ruby on Rails 7 — the frontend half of the same simplification argument
Written by

Udit Mittal

Founder at Boolean Solutions. Twenty years of building and rescuing web, mobile and AI products for SaaS companies and startups — and writing down what actually worked.

Get in touch