Solid Trifecta: When to Keep Redis in Rails 8

Last quarter we migrated a B2B SaaS client off Redis for $360/month in savings. The Solid stack made it possible. Whether your app should follow them off Redis is a different question, and the answer is “it depends on three things.”
Solid Cache, Solid Queue, and Solid Cable (the “Solid Trifecta”) replace Redis for caching, background jobs, and WebSockets. All three are database-backed and ship as defaults in new Rails 8 apps. 37signals runs Solid Cache in production across Basecamp and HEY, handling what used to require 1.1 terabytes of Redis RAM with 80 gigabytes of database storage, an 80% infrastructure cost reduction at their scale.
Across the migrations we’ve shipped this year, the rough split is half fully Redis-free, half hybrid. The decision came down to throughput, data structure usage, and burstiness. Here’s the framework.
What each component replaces #
Each component targets a specific Redis use case:
Solid Cache replaces redis_cache_store. It stores cache entries in a dedicated database table instead of Redis memory. The tradeoff: reads are roughly 40% slower
than Redis, and the cache can be 6x larger because disk is cheaper than RAM. For most Rails apps where cached values are HTML fragments, serialized JSON, or computed reports, single-digit millisecond latency is invisible to users.
Solid Queue replaces Sidekiq and Resque for background job processing. It uses FOR UPDATE SKIP LOCKED for efficient polling, no Redis pub/sub needed. 37signals introduced it in production
at HEY, processing millions of jobs daily. For apps under 100 jobs/second, it performs identically to Sidekiq in wall-clock terms.
Solid Cable replaces Redis as the Action Cable adapter. It polls the database for new messages instead of using Redis pub/sub. This works well for live notifications, dashboard updates, and internal tool chat. Sub-10ms delivery requirements (multiplayer games, collaborative editing, high-frequency dashboards) still need Redis pub/sub or AnyCable.
Keep Redis or drop it: deal-breakers per component #
For each component, there’s a short list of deal-breakers. Hit any of them and Redis stays.
Solid Cache #
Throughput is the deal-breaker. If your app reads cache more than 10,000 times per second, Solid Cache’s 1-2ms PostgreSQL overhead adds up to 10-20 extra seconds of cumulative latency across your request pool. Below that, you won’t notice.
The second question is sneakier. If you use Redis as a data structure server (sorted sets for rate limiting, HyperLogLog for cardinality estimates, Lua scripts for atomic operations) Solid Cache can’t replace any of it. It’s a key-value store, and your data-structure usage stays on Redis even when the cache moves.
There’s also a write pressure concern that bit us on one migration. Very short-lived cache entries (TTL under 60 seconds) generate constant INSERTs and DELETEs. Redis handles this in memory with zero disk I/O; PostgreSQL feels every write.
For everything else - fragment caching, page caching, API response caching, session storage - Solid Cache works. We’ve written a full migration guide with benchmarks.
Solid Queue #
Each enqueue is a database INSERT and each dequeue a SELECT plus UPDATE. Under 100 jobs/second, the database is fast enough that you won’t notice any difference from Sidekiq’s in-memory operations . Above that the gap is measurable, and it widens with traffic spikes.
Latency is the other concern. Solid Queue polls at a configurable interval - default one second. You can push it lower, but polling will never match Redis pub/sub. If your payment webhooks need to fire within 50ms of enqueue, Sidekiq is still faster.
Then there’s the feature question. Solid Queue covers recurring jobs (since 1.0), but Sidekiq Pro’s batches, rate limiting, and unique jobs have years of production hardening that Solid Queue hasn’t matched yet. If you’re paying for Pro and using its features, don’t switch just because database-backed sounds purer.
One more thing most people don’t think about: spiky traffic. Solid Queue handles steady throughput well. A sudden 50x burst - Black Friday, a concert ticket drop - hits the database hard. Redis absorbs spikes in memory. That’s what it was built for.
For apps under 100 jobs/second with tolerance for 1-2 second queue latency? Solid Queue handles it. Our migration guide walks through the move queue by queue.
Solid Cable #
This one is simpler. Solid Cable polls; Redis pushes. If your chat app shows “user is typing” indicators, or you’re building collaborative editing, or anything where 200ms of polling latency feels broken - keep Redis. (Or look at AnyCable for even better performance.) At 10,000+ concurrent WebSocket connections, each poll is a database query - that’s 50,000 SELECTs per second at a 200ms interval. Redis pub/sub handles the same load with a single publish to all subscribers.
For internal dashboards, admin panels, and notification feeds? Solid Cable is fine.
The hybrid architecture that works #
Most production Rails apps we’ve migrated end up here:
# config/environments/production.rb
# Solid Cache for general caching (HTML fragments, API responses)
config.cache_store = :solid_cache_store
# Solid Queue for most background jobs
config.active_job.queue_adapter = :solid_queue
# Redis ONLY for specific workloads:
# - Rate limiting (sorted sets)
# - Sidekiq Pro batches (if you use them)
# - Action Cable (if >1,000 concurrent connections)
This cuts the Redis bill by 60-80% while keeping it where it earns its cost. You don’t have to choose one or the other. Run Solid Queue for email delivery, report generation, and scheduled tasks. Keep Sidekiq for your payment processing queue where latency matters.
Here’s the configuration for running both:
# app/jobs/application_job.rb
class ApplicationJob < ActiveJob::Base
# Default: Solid Queue (database-backed)
end
# app/jobs/payment_webhook_job.rb
class PaymentWebhookJob < ApplicationJob
self.queue_adapter = :sidekiq # Override: Redis-backed
queue_as :critical
end
Migration order: start with the lowest risk #
The safest approach is migrating one component at a time, starting with cache.
Week 1-2: Solid Cache #
Cache is the lowest-risk move. If something goes wrong, you get a cache miss - the app is slower, not broken. Run both cache stores in parallel for a week, comparing hit rates and latency. We wrote about the benchmarks and migration steps in detail.
Week 3-4: Solid Queue (non-critical queues first) #
Begin with email delivery, analytics events, and cleanup jobs. Keep payment processing and time-sensitive webhooks on Sidekiq. Monitor database load - if your connection pool and write throughput can handle it, migrate more queues. Our Solid Queue vs Sidekiq comparison covers the architectural differences.
Week 5+: Evaluate Solid Cable #
This step only applies if you’re using Action Cable and your WebSocket load is modest. Solid Cable has the most noticeable latency difference of the three, so measure before committing.
Track database load at every step #
More Solid components means more database queries. If you’re running PostgreSQL, watch pg_stat_activity for connection counts, pg_stat_user_tables for sequential scans on cache/queue tables, and your overall write throughput. A dedicated database for cache and queue tables
keeps that write pressure off your primary instance.
When NOT to migrate #
Skip the Solid stack when:
If your team is happy with Redis and it costs $50/month, migration has a cost too - leave it alone. There’s no architectural medal for removing a dependency that works. Pre-launch teams should ship the product first and optimize infrastructure after they have traffic to measure; the Solid defaults in new Rails 8 apps are fine for launch, and you can revisit when scaling questions come up. And if your database is already under pressure, adding cache reads, job polling, and WebSocket queries to an overloaded PostgreSQL instance only makes the problem worse. Fix the database first. Consider read replicas or a dedicated queue database before migrating.
Don’t migrate everything at once #
We almost learned this the hard way on a B2B SaaS migration last fall. We moved cache and queue to Solid on the same weekend, didn’t set up a dedicated queue database, and Monday morning the connection pool maxed out at 100 with Solid Queue’s 25 workers running across 4 processes. We rolled back queue, added the separate database, migrated again the following week. No drama, because we’d done cache first and knew the rollback path.
The Solid Trifecta shifts load from Redis to your database. That’s a real architectural tradeoff that requires monitoring and capacity planning . Migrate one component at a time. Measure for a week. Then move the next one.
What we shipped last month #
Across our last few migrations, the typical post-migration shape looks like this. A B2B SaaS on Rails 7.2 had been paying $480/month for Redis on ElastiCache (cache.r6g.large) handling cache, Sidekiq, and Action Cable. PostgreSQL ran on RDS.
We moved fragment and API response caching to Solid Cache. Cache size went from 2GB (limited by Redis memory) to roughly 50GB on disk. Average read latency increased from 0.3ms to 1.1ms; nobody noticed. P95 page load actually improved because the cache hit rate climbed from 68% to 91% with the larger cache footprint.
Solid Queue took over email delivery, report generation, and scheduled cleanup at 200 jobs/minute steady. Active Job Continuations made the long-running nightly import deploy-safe for the first time.
Sidekiq stayed for the payment webhook queue (needs sub-second latency) and the real-time inventory sync (2,000 jobs/minute bursts during peak hours). Redis also stayed for Action Cable, where 1,200 concurrent WebSocket connections power the admin dashboard.
The new monthly Redis bill landed at $120, a 75% cut. The hybrid approach let us keep Redis only where it earned its cost.
Want the same result? We’ve shipped four of these migrations on production Rails 7+ apps this year. We’ll review your Redis usage, identify which workloads can move, and build the migration plan. Book a technical review : 45 minutes, one senior Rails engineer, a written recommendation.
If you’re planning a Solid stack migration, these are the companion pieces: our Solid Cache benchmarks and migration steps cover the cache move in detail, and the Solid Queue vs Sidekiq comparison digs into the architectural differences. For the deployment side, Kamal in Rails 8 and the Docker production guide round out the stack.
Further reading #
- 37signals: Solid Cache - a disk-backed Rails cache - architecture and production results from Basecamp/HEY
- 37signals: Introducing Solid Queue - database-backed Active Job backend
- 37signals: Solid Queue 1.0 released - recurring jobs, mission-critical reliability
- BigBinary: Benchmarking caching in Rails with Redis vs alternatives - independent performance comparison
- Simple Thread: I Love You, Redis, But I’m Leaving You for SolidQueue - real migration story with production numbers
- Rails Guides: Caching with Rails - official caching documentation
- Rails Guides: Multiple Databases - separate databases for cache and queue tables