Welcome to the Rails "Solid" Era

If you’re new to Rails or you’ve recently heard about Rails 8, you’ve probably come across these three mysterious names: Solid Cache, Solid Cable and Solid Queue. These three gems form what we call the "Solid Triumvirate" (or "Solid Trifecta" in English) and represent one of Rails' most significant evolutions in years.


But why all the excitement? Because these three tools allow you to build a Rails application complete and performant without Redis or any external dependency. No more headaches configuring multiple services! Everything runs with your database.


In this series of articles, we will explore in depth each component of the triumvirate, understand how they work, and most importantly, learn to use them with concrete examples. Whether you’re a junior developer or simply curious, by the end of this read you’ll master these three essential Rails 8 tools.


We will also talk a lot about Redis, so if you want to learn what it is or refresh your memory, read my ultra-complete article on the subject: Redis and Rails 8 : The Complete Guide for Junior Developers


Why does the Solid Triumvirate exist?

The traditional problem

Before Rails 8, if you wanted to build a modern Rails application with advanced features, your stack generally looked like this:

  1. PostgreSQL or MySQL : your primary database
  2. Redis : for the cache
  3. Redis or Sidekiq : for background jobs
  4. Redis : for Action Cable (real-time features)


Do you see the pattern? Redis everywhere! And while Redis is excellent, it introduces several constraints:

  1. Deployment complexity : one more service to manage, monitor, and maintain
  2. Additional costs : on platforms like Heroku, every add-on has a price
  3. External dependency : if Redis goes down, several parts of your app go down too
  4. Learning curve : another technology to learn for juniors



The "Solid" philosophy

The Basecamp team (the creators of Rails) had a simple but powerful reflection:

"What if we used our database for everything?"

With modern SSDs (notably NVMe), disk storage has become fast enough to rival RAM in many use cases. Moreover, modern databases like PostgreSQL and MySQL have made huge performance gains.


The result? A Rails that’s simpler, lighter, and just as performant for 80% of applications.

Solid Cache: The Database-Based Cache

What is cache, exactly?

Before diving into Solid Cache, let’s understand what cache is. Imagine you have an e-commerce site with a homepage that shows the most popular products. On each visit, the server must:

  1. Query the database
  2. Calculate the statistics
  3. Generate the HTML
  4. Send the response

If you have 1,000 visitors per minute, you repeat this operation 1,000 times... to display exactly the same content! It’s a waste of resources.

The cache solves this problem by storing the result of this costly operation in memory. Next time, instead of recomputing everything, you simply retrieve the stored result. It’s like keeping your favorite coffee mug on your desk rather than in the kitchen cabinet.

Solid Cache: How does it work?

Solid Cache replaces traditional solutions (Redis, Memcached) with a database-based caching system based on your database.


The architecture

Solid Cache uses a simple table in your database called solid_cache_entries. Here’s its structure :


# db/cache_schema.rb
create_table "solid_cache_entries", force: :cascade do |t|
t.binary "key", null: false # Cache key
t.binary "value", null: false # Stored value
t.datetime "created_at", null: false
t.integer "key_hash", limit: 8, null: false # Key hash for fast lookup
t.integer "byte_size", limit: 4, null: false # Entry size
end


The principle :

  1. When you cache data, it is stored in this table
  2. When you retrieve it, Rails runs a ultra-fast SQL query on the index key_hash
  3. Entries are automatically cleaned according to your configuration


Why is it fast even with disk storage?

You might be wondering: "A disk-based database can’t be as fast as Redis in RAM, right?"


Excellent question! Here’s why it works:

  1. Modern SSDs are ultra-fast : NVMe reach impressive read/write speeds
  2. Database-level caching : PostgreSQL and MySQL cache frequently accessed data in RAM
  3. Massive storage : With disk, you can store 100x more data than Redis, meaning fewer cache misses
  4. Longer retention : Basecamp keeps 10 TB of cache for 60 days!

Installation and Configuration

On Rails 8

Good news: Solid Cache is enabled by default on Rails 8! Nothing to do when creating a new app:

rails new mon_app
cd mon_app
rails db:migrate


That’s it! Solid Cache is already configured in production.


On Rails 7.1+ (manual installation)

If you’re using an older version of Rails 8:

# Add the gem
bundle add solid_cache
# Install Solid Cache
bin/rails solid_cache:install
# This will create:
# - config/cache.yml
# - db/cache_schema.rb


Then configure your config/database.yml:

production:
primary:
<<: *default
database: my_app_production
cache:
<<: *default
database: my_app_cache_production
migrations_paths: db/cache_migrate


And in config/environments/production.rb :

config.cache_store = :solid_cache_store


Configuration in config/cache.yml

default: &default
store_options:
max_age: <%= 60.days.to_i %> # Maximum retention duration
max_size: <%= 256.megabytes %> # Maximum cache size
namespace: <%= Rails.env %>
production:
database: cache
<<: *default
development:
<<: *default

Practical Examples

Example 1: Cache a costly query

# app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
# Without cache: this query runs on every visit
# @products = Product.includes(:category).where(published: true).order(views: :desc).limit(10)
# With cache: this query only runs once per hour
@products = Rails.cache.fetch('popular_products', expires_in: 1.hour) do
Product.includes(:category)
.where(published: true)
.order(views: :desc)
.limit(10)
end
end
end


How it works:

  1. The first time, Rails finds nothing in the cache
  2. The block executes, the query is performed
  3. The result is stored in solid_cache_entries with the key "popular_products"
  4. Subsequent visits retrieve the cache result directly
  5. After 1 hour, the entry expires and the cycle restarts


Example 2: Cache a complex calculation

# app/models/user.rb
class User < ApplicationRecord
def reputation_score
Rails.cache.fetch("user_#{id}_reputation", expires_in: 5.minutes) do
calculate_complex_reputation
end
end
private
def calculate_complex_reputation
# Costly calculation on multiple table
(posts.sum(:likes) * 2) +
(comments.sum(:upvotes) * 1.5) +
(achievements.count * 10) -
(posts.sum(:dislikes) * 0.5)
end
end

Example 3: Cache a partial view

In your views, you can use fragment caching:

Rails automatically generates a unique key based on:

<!-- app/views/products/_product.html.erb -->
<% cache product do %>
<div class="product">
<h2><%= product.name %></h2>
<p><%= product.description %></p>
<span class="price"><%= number_to_currency(product.price) %></span>
</div>
<% end %>


The model (Product)

  1. The product’s ID
  2. The last update (updated_at)
  3. If the product changes, the cache is automatically invalidated!

Example 4: Manage the cache manually

# Write to the cache
Rails.cache.write('my_key', 'my_value', expires_in: 10.minutes)
# Read from the cache
value = Rails.cache.read('my_key')
# Delete a cache entry
Rails.cache.delete('my_key')
# Increment a counter
Rails.cache.increment('count_visitors')
# Decrement a counter
Rails.cache.decrement('count_visitors')
# Clear the entire cache
Rails.cache.clear

Maintenance Operations

Enable caching in development

By default, caching is disabled in development. To enable it:

This command creates a file tmp/caching-dev.txt. Restart it to disable caching.

rails dev:cache


Monitoring the cache

# Console Rails
rails c
# Voir toutes les entrées
SolidCache::Entry.count
# Voir la taille totale du cache
SolidCache::Entry.sum(:byte_size) / 1.megabyte
# => 145.2 MB
# Voir les entrées les plus récentes
SolidCache::Entry.order(created_at: :desc).limit(10)

Solid Cache vs Redis: When to use which?


Criterion
Solid Cache
Redis
Speed
Fast (disk + DB cache)
Very fast (pure RAM)
Capacity
Massive (several TBs)
Limited (RAM is expensive)
Persistence
Yes, stored on disk
Optional
Simplicity
Very simple (built into Rails)
Requires external configuration
Cost
Low (uses disk storage)
Higher (RAM-based)
Use Cases
Small to medium apps
High-performance apps

Use Solid Cache if:

  1. You’re starting a new Rails 8 project
  2. You want to simplify your infrastructure
  3. You don’t need extreme performance
  4. You want to store a lot of data in cache


Keep Redis if:

  1. You need maximum performance
  2. You use Redis advanced features (pub/sub, sorted sets). Not sure what that is? Go read my article on the subject: Redis and Rails 8: The Complete Guide for Junior Developers
  3. You already have a well-tuned Redis infrastructure

Conclusion: Solid Cache, the native Rails super cache

Solid Cache is Rails’ cache reimagined for simplicity and performance. By leveraging Active Record and a SQL base, it eliminates the friction associated with Redis while offering a familiar and powerful API. Whether it’s to optimize the performance of your views, reduce calls to external services, or accelerate your queries, Solid Cache integrates naturally into your Rails stack.

With Rails 8 officially adopting it, it’s time to say goodbye to complex configurations and enjoy a robust, readable, and easy-to-maintain cache.

🚀 Fewer dependencies, more clarity. Solid Cache is Rails’ cache like we’ve always dreamed of.