Skip to content

Web Development · Backend

Ruby on Rails 8: What the Comeback Looks Like in Production

Rails 8 ships Solid Queue, Solid Cache, Solid Cable, and Kamal 2. Together they make it possible to run a production app on one server, without Redis, without a separate Node process, and without external managed services for the basics.

Anurag Verma

Anurag Verma

6 min read

Ruby on Rails 8: What the Comeback Looks Like in Production

Sponsored

Share

Rails 8 arrived in November 2024 and did something unusual for a framework update: it reduced the number of services you need to run a production app. Most framework updates add features that require more infrastructure. Rails 8 replaced external services with database-backed alternatives that work out of the box.

The result is that a new Rails 8 app can ship to production with just a server, a database, and a container — and it still gets queued background jobs, caching, WebSockets, and HTTPS without reaching for Redis, Memcached, or a managed queue service.

What Changed

Rails 8 ships four things that matter for production deployments:

Solid Queue replaces the need for Redis as a background job backend. It uses your existing database to store and process jobs. For most apps, database-backed queuing is fast enough and removes a dependency.

Solid Cache replaces Memcached or Redis for fragment and low-level caching. Again, backed by your database.

Solid Cable makes Action Cable (WebSockets) work without Redis as a pub/sub layer.

Kamal 2 is the deployment tool that’s now bundled with Rails. It uses Docker to deploy your app to any server — a $6 VPS works — with built-in SSL, a reverse proxy (Kamal Proxy, which replaced Traefik), and zero-downtime deploys.

Thruster handles asset compression and HTTP/2 push when you deploy with Kamal. Nginx is no longer needed in the standard configuration.

Solid Queue in Practice

Background jobs in Rails use the Active Job interface regardless of the backend:

class SendWelcomeEmailJob < ApplicationJob
  queue_as :default

  def perform(user)
    UserMailer.with(user: user).welcome_email.deliver_now
  end
end

That code works with any Active Job backend. What changes with Solid Queue is that you configure it with a YAML file and it reads from your database, not from a separate Redis connection:

# config/queue.yml
default: &default
  dispatchers:
    - polling_interval: 1
      batch_size: 500
  workers:
    - queues: "*"
      threads: 3
      processes: 2
      polling_interval: 0.1

production:
  <<: *default

The job record lives in your database, which means you can query it with ActiveRecord, join it to your own tables, and see the full job state without a separate Redis monitoring tool.

For apps that were using Sidekiq with Redis, this is a real simplification at low-to-medium volume. Solid Queue’s throughput is lower than Sidekiq at high volume (Redis is faster than a relational database for queue operations), but for apps processing thousands rather than millions of jobs per day, the difference is irrelevant.

Authentication Generator

Rails 8 ships a rails generate authentication command that creates a complete session-based auth system in your app:

rails generate authentication

This creates:

  • A User model with password hashing via BCrypt
  • A Session model for tracking active sessions
  • SessionsController for login/logout
  • PasswordsController for password reset via email
  • The necessary routes and views
  • A Current model using ActiveSupport::CurrentAttributes
# Generated current.rb
class Current < ActiveSupport::CurrentAttributes
  attribute :session
  delegate :user, to: :session, allow_nil: true
end

The generated code is readable and extensible. It’s not a gem you install and configure — it’s code that lives in your app and you modify directly.

This covers the 90% case: email/password login with session management. For OAuth providers (Google, GitHub), you still reach for Omniauth. But a significant fraction of apps only need password auth, and the generator handles it cleanly.

Kamal 2: Docker Deployment to Any Server

Kamal 2 makes deploying a Rails app to a bare server about as straightforward as pushing to Heroku, but without the per-dyno pricing:

# config/deploy.yml
service: myapp
image: user/myapp

servers:
  web:
    - 192.168.0.1
  job:
    hosts:
      - 192.168.0.1
    cmd: bin/jobs

proxy:
  ssl: true
  host: myapp.com

registry:
  username: dockerhub-user
  password:
    - KAMAL_REGISTRY_PASSWORD
kamal setup    # First deploy: installs Docker, sets up the proxy, deploys
kamal deploy   # Subsequent deploys: builds, pushes, and rolls out with zero downtime

Kamal handles:

  • Building the Docker image
  • Pushing to a registry
  • SSH-ing into your servers
  • Running the new container
  • Health-checking before removing the old container
  • Rolling back if the health check fails

The proxy (Kamal Proxy) handles HTTPS via Let’s Encrypt automatically. You get SSL without configuring nginx or Certbot.

A $6/month Hetzner VPS can run a Rails 8 app for a small production workload. For teams used to paying for Heroku or Render dynos, this is a significant reduction in running costs for apps with modest traffic.

No Node.js by Default

Rails 7 introduced importmaps as an alternative to webpack and esbuild, but they felt like a workaround. Rails 8 makes the no-Node path fully supported and the default for new apps.

New Rails 8 apps use Propshaft (the asset pipeline), importmaps for JavaScript, and Tailwind CSS via a standalone CLI (which downloads a Tailwind binary, not an npm package). You can add a Node-based build process if you need it for a JavaScript-heavy frontend, but it’s opt-in.

For Rails apps that are primarily server-rendered with light JavaScript — which is most admin tools, internal dashboards, content sites, and SaaS apps — the no-Node setup works well and eliminates a whole category of dependency management.

Who Should Look at Rails 8

Rails 8 is a good choice in 2026 for teams where:

  • The primary language is Ruby, or the team has existing Rails experience
  • The app is server-rendered with limited JavaScript complexity
  • Minimizing external service dependencies matters (compliance, budget, operational simplicity)
  • The deployment target is VPS rather than a PaaS

It’s less attractive when:

  • The team is stronger in JavaScript/TypeScript (Node, Next.js are better fits)
  • The app has a complex React or Vue frontend (Rails becomes just an API layer, and something like FastAPI may be lighter)
  • High-concurrency requirements exceed what a multi-threaded Ruby process handles efficiently (Go or Elixir may be better suited)

The Reality

Rails had a rough few years as JavaScript frameworks dominated the conversation. Its conventions felt dated; its asset pipeline was painful. That period led to real improvements — first Hotwire for reactive UIs without JavaScript frameworks, then Rails 7’s modernized toolchain, now Rails 8’s self-contained production defaults.

The framework is in its best shape in years. The community is active. Gem quality is high. The productivity for CRUD-heavy apps is still hard to beat — a resource scaffold generates a complete model, controller, views, migrations, and tests in one command.

Teams that have written Rails off because of 2018-era complaints should spend a day with a new Rails 8 project. The experience is different from what they remember.

Sponsored

Sponsored

Discussion

Join the conversation.

Comments are powered by GitHub Discussions. Sign in with your GitHub account to leave a comment.

Sponsored