---
name: caching-strategies
description: >-
Implements Rails caching patterns for performance optimization. Use when
adding fragment caching, Russian doll caching, low-level caching, cache
invalidation, or when user mentions caching, performance, cache keys,
or memoization. WHEN NOT: General query optimization (use
performance-optimization), background job processing, or problems caused by
N+1 queries rather than missing caches.
paths: "app/views/**/*.erb, app/controllers/**/*.rb"
---
# 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
```ruby
# 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:
```bash
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
```erb
<%# app/views/events/_event.html.erb %>
<% cache event do %>
<%= event.name %>
<%= event.description %>
<%= render event.venue %>
<% end %>
```
### Cache Key Components
Rails generates cache keys from:
- Model name
- Model ID
- `updated_at` timestamp
- Template digest (automatic)
```ruby
# Generated key example:
# views/events/123-20240115120000000000/abc123digest
```
### Custom Cache Keys
```erb
<%# 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:
```erb
<%# app/views/events/show.html.erb %>
<% cache @event do %>
<%= @event.name %>
<% @event.vendors.each do |vendor| %>
<% cache vendor do %>
<%= render partial: "vendors/card", locals: { vendor: vendor } %>
<% end %>
<% end %>
<% end %>
```
Use `touch: true` on `belongs_to` associations to cascade invalidation up the chain. See [cache-invalidation.md](references/cache-invalidation.md) for examples.
## Collection Caching
### Efficient Collection Rendering
```erb
<%# 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](references/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](references/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](references/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](references/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](references/low-level-caching.md) - fetch/read/write, service objects, query objects, memoization
- [cache-invalidation.md](references/cache-invalidation.md) - expiration strategies, manual invalidation, touch, counter caches
- [http-caching-and-testing.md](references/http-caching-and-testing.md) - ETags, Cache-Control, spec configuration, monitoring