Caching Strategies for Rails 8
Overview
Rails provides multiple caching layers:
-
Fragment caching: Cache view partials
-
Russian doll caching: Nested cache fragments
-
Low-level caching: Cache arbitrary data
-
HTTP caching: Browser and CDN caching
-
Query caching: Automatic within requests
Quick Start
config/environments/development.rb
config.action_controller.perform_caching = true config.cache_store = :memory_store
config/environments/production.rb
config.cache_store = :solid_cache_store # Rails 8 default
OR
config.cache_store = :redis_cache_store, { url: ENV["REDIS_URL"] }
Enable caching in development:
bin/rails dev:cache
Cache Store Options
Store Use Case Pros Cons
:memory_store
Development Fast, no setup Not shared, limited size
:solid_cache_store
Production (Rails 8) Database-backed, no Redis Slightly slower
:redis_cache_store
Production Fast, shared Requires Redis
:file_store
Simple production Persistent, no Redis Slow, not shared
:null_store
Testing No caching N/A
Fragment Caching
Basic Fragment Cache
<%# app/views/events/_event.html.erb %> <% cache event do %> <article class="event-card"> <h3><%= event.name %></h3> <p><%= event.description %></p> <time><%= l(event.event_date, format: :long) %></time> <%= render event.venue %> </article> <% end %>
Cache Key Components
Rails generates cache keys from:
-
Model name
-
Model ID
-
updated_at timestamp
-
Template digest (automatic)
Generated key example:
views/events/123-20240115120000000000/abc123digest
Custom Cache Keys
<%# With version %> <% cache [event, "v2"] do %> ... <% end %>
<%# With user-specific content %> <% cache [event, current_user] do %> ... <% end %>
<%# With explicit key %> <% cache "featured-events-#{Date.current}" do %> <%= render @featured_events %> <% end %>
Russian Doll Caching
Nested caches where inner caches are reused when outer cache is invalidated:
<%# app/views/events/show.html.erb %> <% cache @event do %> <h1><%= @event.name %></h1>
<section class="vendors"> <% @event.vendors.each do |vendor| %> <% cache vendor do %> <%= render partial: "vendors/card", locals: { vendor: vendor } %> <% end %> <% end %> </section>
<section class="comments"> <% @event.comments.each do |comment| %> <% cache comment do %> <%= render comment %> <% end %> <% end %> </section> <% end %>
Use touch: true on belongs_to associations to cascade invalidation up the chain. See cache-invalidation.md for examples.
Collection Caching
Efficient Collection Rendering
<%# Caches each item individually %> <%= render partial: "events/event", collection: @events, cached: true %>
<%# With custom cache key %> <%= render partial: "events/event", collection: @events, cached: ->(event) { [event, current_user.admin?] } %>
Low-Level Caching
Use Rails.cache.fetch with a block for the most common pattern. See low-level-caching.md for:
-
Basic read/write/fetch examples
-
Caching in service objects
-
Caching in query objects
-
Instance variable memoization
-
Request-scoped memoization with CurrentAttributes
Cache Invalidation
Three strategies: time-based expiration, key-based expiration (using updated_at ), and manual deletion. See cache-invalidation.md for:
-
Time-based and key-based expiration
-
Manual invalidation in model callbacks and services
-
Pattern-based deletion (delete_matched )
-
touch: true for Russian doll cascade
-
Built-in and custom counter caches
HTTP Caching
Use stale? for conditional GET (ETags/Last-Modified) and expires_in for Cache-Control headers. See http-caching-and-testing.md for full examples.
Testing Caching
Use a :caching metadata tag to enable caching in specs. See http-caching-and-testing.md for:
-
rails_helper.rb configuration
-
Testing cached view invalidation
-
Testing cache invalidation in services
-
Performance monitoring and instrumentation
Checklist
-
Cache store configured for environment
-
Fragment caching on expensive partials
-
touch: true on belongs_to for Russian doll
-
Collection caching with cached: true
-
Low-level caching for expensive queries
-
Cache invalidation strategy defined
-
Counter caches for counts
-
HTTP caching headers for API
-
Cache warming for cold starts (if needed)
-
Monitoring for hit/miss rates
References
-
low-level-caching.md - fetch/read/write, service objects, query objects, memoization
-
cache-invalidation.md - expiration strategies, manual invalidation, touch, counter caches
-
http-caching-and-testing.md - ETags, Cache-Control, spec configuration, monitoring