Rails 8: Solid Queue, Kamal, and the Future of Rails Deployment
Rails 8 ships with built-in job queuing, containerized deployment tools, and a modern authentication system. Here's what changed and how to upgrade.
Rails 8: A Major Step Forward for Modern Web Applications
Rails 8, released in November 2024, represents a significant evolution for the Rails framework. This release introduces three major features that fundamentally change how Rails developers approach job processing, deployment, and authentication: Solid Queue (built-in job queuing), Kamal (containerized deployment), and Authentication Generator (out-of-the-box user auth). These additions reflect the Rails team’s commitment to reducing external dependencies and providing production-ready solutions out of the box.
For developers maintaining Rails applications or starting new projects, Rails 8 offers tangible improvements in operational simplicity, deployment flexibility, and time-to-market. Let’s explore what changed, why it matters, and how to get started.
What’s New in Rails 8
Solid Queue: Built-In Job Processing
For years, Rails developers relied on external job queues like Sidekiq, Resque, or Delayed Job. Solid Queue changes this by providing a production-grade job queuing system as part of Rails itself.
Key features:
- Database-backed queue: Jobs are stored in your PostgreSQL or MySQL database—no Redis or separate infrastructure required
- Concurrent processing: Supports multiple processes and threads for parallel job execution
- Reliable delivery: Built-in retry logic, error handling, and job status tracking
- Simple configuration: Minimal setup compared to external queue systems
Solid Queue is ideal for applications that:
- Run on single-server deployments or small clusters
- Already use PostgreSQL/MySQL and want to reduce infrastructure complexity
- Have moderate job volumes (thousands to tens of thousands per hour)
- Want tighter integration with Rails code
Kamal: Container-Based Deployment Without Kubernetes
Kamal, originally extracted from Hey’s deployment infrastructure, is now a first-class Rails tool. It provides an alternative to Kubernetes that’s simpler for small-to-medium teams.
What Kamal does:
- Docker containers: Automatically builds and deploys Docker images to your servers
- Zero-downtime deployments: Orchestrates rolling updates with health checks
- SSH-based deployment: No complex orchestration layer—just SSH and Docker
- Multi-server support: Deploy to multiple machines with automatic load balancing
- Cost-effective: Works with any VPS provider (DigitalOcean, Linode, AWS EC2, etc.)
Unlike Kubernetes, Kamal is opinionated and designed specifically for Rails applications, reducing operational overhead.
Authentication Generator
Rails 8 includes a new rails generate authentication command that scaffolds a complete authentication system, including:
- User model with password hashing (bcrypt)
- Session management
- Password reset functionality
- Email verification (optional)
This addresses a long-standing pain point: every Rails developer had to either write authentication from scratch or integrate Devise, which, while powerful, adds complexity to simple applications.
Getting Started with Rails 8
Creating a New Rails 8 Application
gem install rails --version '~> 8.0'
rails new myapp
cd myapp
bundle install
Rails 8 defaults to using Solid Queue for job processing and includes the authentication generator by default.
Generating Authentication
rails generate authentication
rails db:migrate
This creates:
-
Usermodel with password hashing - Authentication routes and controller
- Session management helpers
- Migration files
The generated code is intentionally simple and modifiable—not a black-box gem.
Configuring Solid Queue
Basic Setup
Solid Queue is installed by default. Configuration is straightforward:
# config/solid_queue.yml
production:
dispatchers:
- batch_size: 500
polling_interval: 1
workers:
- threads: 5
polling_interval: 1
This configures one dispatcher (sends jobs to workers) and one worker process with 5 concurrent threads.
Enqueuing Jobs
# Define a job
class SendWelcomeEmailJob < ApplicationJob
queue_as :default
def perform(user_id)
user = User.find(user_id)
UserMailer.welcome(user).deliver_later
end
end
# Enqueue it
SendWelcomeEmailJob.perform_later(user.id)
# Schedule for later
SendWelcomeEmailJob.set(wait: 1.hour).perform_later(user.id)
This syntax is identical to previous Rails versions, making migration from other queue systems straightforward.
Monitoring Job Status
Solid Queue stores job data in the database, making it queryable:
# Check job counts
SolidQueue::Job.where(status: :pending).count
SolidQueue::Job.where(status: :failed).count
# Find a specific job
job = SolidQueue::Job.find_by(job_id: "abc123")
puts job.error if job.failed?
You can also use API Request Builder to integrate job monitoring with external dashboards by querying Rails endpoints.
Deploying with Kamal
Prerequisites
Kamal requires:
- Docker installed on your local machine
- SSH access to your deployment servers
- A container registry (Docker Hub, GitHub Container Registry, etc.)
Kamal Configuration
Rails 8 generates a config/deploy.yml file:
service: myapp
image: username/myapp
registries:
docker:
username: <%= ENV['DOCKER_USERNAME'] %>
password: <%= ENV['DOCKER_PASSWORD'] %>
servers:
web:
hosts:
- 1.2.3.4
- 1.2.3.5
job:
hosts:
- 1.2.3.6
cmd: ./bin/solid_queue start
env:
clear:
RAILS_ENV: production
secret:
- RAILS_MASTER_KEY
- DATABASE_URL
volumes:
- "log:/rails/log"
- "tmp:/rails/tmp"
traefik:
image: traefik:v3
ports:
- "80:80"
- "443:443"
options:
publish:
- "443:443/tcp"
- "80:80/tcp"
Key features:
-
Separate
webandjobroles for independent scaling - Environment variables managed securely
- Built-in Traefik reverse proxy for TLS and routing
Deploying
# First deployment (sets up servers)
kamal setup
# Redeploy after code changes
kamal deploy
# Roll back to previous version
kamal rollback
# Check logs
kamal logs
# SSH into a server
kamal ssh web
Step-by-Step Upgrade Path
If you’re running Rails 7, upgrading to Rails 8 is relatively straightforward:
1. Update Gemfile
gem 'rails', '~> 8.0'
2. Run Bundle Update
bundle update rails
3. Run Rails Upgrade Command
bundle exec rails app:update
This updates configuration files and generates new files (like Kamalfile) without overwriting your code.
4. Review Breaking Changes
Key breaking changes in Rails 8:
- Ruby 3.1+: Rails 8 requires Ruby 3.1 or newer
- Zeitwerk eager loading: Stricter constant loading in development
- JSON serialization: Default JSON encoder has changed behavior
- SQLite improvements: New default behavior for SQLite connections
Consult the Rails 8 upgrade guide for detailed instructions.
5. Test Job Processing
If migrating from Sidekiq or another queue:
# In your test suite
require 'rails_helper'
describe SendWelcomeEmailJob do
it 'sends a welcome email' do
user = create(:user)
expect {
SendWelcomeEmailJob.perform_now(user.id)
}.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end
Use perform_now in tests instead of enqueueing, ensuring synchronous execution.
Common Pitfalls and How to Avoid Them
Pitfall 1: Database Bottlenecks with Solid Queue
Problem: If you have extremely high job volumes (100k+ jobs/hour), a database-backed queue may become a bottleneck.
Solution: Solid Queue is ideal for most applications, but if you hit limits, migrate to Sidekiq—job code remains the same:
# Your job code works with both Solid Queue and Sidekiq
class MyJob < ApplicationJob
queue_as :default
def perform(*args)
# code here
end
end
Pitfall 2: Kamal SSH Access Not Configured
Problem: Kamal relies on SSH keys for server access; misconfigured credentials block deployments.
Solution: Pre-configure SSH keys on all target servers:
# On your local machine
ssh-copy-id -i ~/.ssh/id_rsa [email protected]
# Test connection
ssh [email protected] 'docker --version'
Pitfall 3: Missing Environment Variables in Production
Problem: config/deploy.yml references environment variables; missing ones crash deployments.
Solution: Validate variables before deploying:
kamal env check
And use a .env.production.local file locally:
# .env.production.local
DATABASE_URL=postgresql://...
RAILS_MASTER_KEY=...
Pitfall 4: Not Running Solid Queue in Background
Problem: Forgetting to start the Solid Queue worker process means jobs never process.
Solution: With Kamal, define a separate job role in config/deploy.yml:
servers:
job:
hosts:
- 1.2.3.6
cmd: ./bin/solid_queue start
Or manually in production:
bin/solid_queue start
Why Rails 8 Matters
Rails 8 represents a philosophical shift: instead of relying on external gems for essential functionality, Rails now bundles production-ready solutions. This has several implications:
- Reduced complexity: New developers can start with fewer dependencies
- Better integration: Authentication and job processing are tightly integrated with Rails
- Easier deployment: Kamal removes the need to learn Kubernetes for most teams
- Lower operational costs: Database-backed queuing and SSH-based deployment reduce infrastructure overhead
For small-to-medium teams, Rails 8 can significantly reduce time-to-production and operational burden. For larger teams, the built-in tools provide solid baselines—you can still integrate Sidekiq, Devise, or Kubernetes if needed.
Testing Your Configuration
Before deploying, thoroughly test your setup:
# Test job enqueueing
MyJob.perform_later
assert_enqueued_with(job: MyJob)
# Test Solid Queue processing
require 'solid_queue/testing'
MyJob.perform_now # In tests, process immediately
For deployment validation, you can use API Request Builder to test endpoints before and after deployment:
# Test health endpoint
curl -X GET https://myapp.com/health
And use Webhook Tester to capture deployment notifications:
# Kamal can POST to a webhook after deployment
kamal deploy
# Your webhook endpoint receives:
# {
# "event": "deployed",
# "service": "myapp",
# "timestamp": "2024-12-15T10:30:00Z"
# }
Conclusion
Rails 8 is a mature release that reflects years of production experience at companies like Basecamp and Hey. Solid Queue, Kamal, and the authentication generator reduce boilerplate and operational complexity without sacrificing flexibility.
For developers upgrading from Rails 7, the migration is straightforward. For new projects, Rails 8 provides a faster path to a deployable application.
The key takeaway: Rails now provides sensible defaults for deployment, job processing, and authentication—you can start simple and add complexity only when you need it.