Redis and Rails 8: The Complete Guide for Junior Developers
Introduction: Why Redis will change the way you develop
Are you starting with Rails and hearing about Redis everywhere? In discussions about performance, caching, user sessions... Redis seems to be the magical solution to all problems. But what exactly is it? And above all, how do you use it concretely in your Rails applications?
In this article, we’ll explore Redis from A to Z: what it is, why it’s so fast, how it compares to traditional databases, and above all how to integrate it easily into Rails 8. Get ready to discover a tool that will become indispensable in your developer toolbox!
Some aspects may seem a little complex to understand. That’s normal! This touches on optimization challenges for applications that must handle thousands, even millions of users. Don’t panic :)
What is Redis exactly?
The simple definition
Redis (Remote Dictionary Server) is a key-value database that stores all its data in memory (RAM). Think of it as a giant ultra-fast dictionary where you can store and retrieve information instantly.
Created in 2009 by Salvatore Sanfilippo, Redis is today one of the most popular NoSQL databases in the world. More than 30,000 companies use it, including British Airways, HackerRank and MGM Resorts. In 2025, Redis 8.2 is the latest major version available, delivering impressive performance improvements: up to 91% faster than Redis 7.2!
The key concept: RAM
The fundamental difference between Redis and a traditional database like PostgreSQL or MySQL? Where data is stored.
- Traditional database : stores data on disk (HDD or SSD)
- Redis : stores data in RAM
This difference may seem minor, but it’s enormous in terms of performance:
- RAM access: 100 nanoseconds
- SSD access: 100 microseconds (1,000 times slower!)
100 microseconds may already not seem like much, you’ll say? Consider the following analogy: Imagine you’re looking for a book in your library. With a traditional database, you have to go to another room to find it. With Redis, the book is already in your hands.
Redis data structures
Redis isn’t just a simple key-value store. It offers advanced data structures that make it extremely versatile. It’s a bit like having several types of containers to store different kinds of objects.
Below, I’ll show you some examples of how data is structured in Redis.
1. Strings
The most basic structure. A key points to a text (or binary) value.
Example usage:
Perfect use cases:
- Counters (article views, likes)
- HTML fragment cache
- Temporary session tokens
- Configuration values
Capacity: up to 512 MB per value!
2. Hashes
Imagine a Ruby hash stored in Redis. It’s perfect for representing objects with several attributes.
Example usage:
Perfect use cases:
- User profiles
- Object configurations
- Multi-tenant metrics
- Lightweight structured data
Advantage: very memory-efficient for storing many small objects
3. Lists
Ordered lists of elements. Think of a Ruby array, but in Redis. Perfect for queues!
Example usage:
Perfect use cases:
- Message queues
- Activity timelines (news feed)
- History of recent actions
- Notification system
Important note: operations at the head and tail of the list are O(1) — ultra-fast!
4. Sets
Collections of unique unordered elements. Exactly like a Set in Ruby.
Example usage:
Perfect use cases:
- Tag systems
- Unique friend/follower lists
- Tracking of unique IP addresses
- Simple many-to-many relationships
Bonus: set operations (union, intersection, difference) in O(N)
5. Sorted Sets
The most powerful structure! Unique elements with a score that determines the order.
Example usage:
Perfect use cases:
- Leaderboards (rankings)
- Priority queues
- Rate limiting
- Time-ordered data
Performance: all basic operations in O(log N)
Redis vs Traditional Databases: The Match
Now that you know Redis, let’s compare it with PostgreSQL or MySQL to understand when to use one or the other.
Comparison Table
|
Criterion
|
Redis
|
PostgreSQL/MySQL
|
|---|---|---|
|
Storage
|
In memory (RAM)
|
On disk (HDD/SSD)
|
|
Read speed
|
Sub-millisecond
|
Milliseconds to seconds
|
|
Data model
|
Key-value + structures
|
Relational (tables)
|
|
Complex queries
|
Limited
|
Full SQL, JOINs
|
|
*ACID Transactions ()**
|
Partial
|
Complete
|
|
Persistence
|
Optional
|
Native
|
|
Capacity
|
Limited by RAM
|
Limited by disk
|
|
Cost
|
RAM => more expensive
|
Disk => cheaper
|
(*) Quick look at ACID transactions: what is it?
An ACID transaction is a database operation that respects four essential properties: Atomicity, Consistency, Isolation and Durability. These properties guarantee reliability and data integrity, even in case of error or failure.
🔹 Atomicity
- All or nothing: a transaction is indivisible. Either all operations it contains are executed, or none are.
- Example: during a bank transfer, if the debit from account A fails, the credit to account B should not occur either.
🔹 Consistency
- The database moves from a valid state to another valid state after the transaction.
- Integrity rules (constraints, relationships, etc.) must always be respected.
- Example: an inventory should never contain a negative number of items after an update.
🔹 Isolation
- Concurrent transactions must not interfere with each other.
- Each transaction should execute as if it were the only one on the system.
- This avoids side effects like reading data that has not been committed by another transaction.
🔹 Durability
- Once a transaction is committed, its effects are permanent, even in a system crash.
- The modified data is saved
Redis offers only partial support since it guarantees only atomicity and a form of isolation. It does not guarantee consistency nor durability.
✅ Atomicity
- Redis guarantees that the commands of a transaction are executed all or nothing.
- If an error occurs before execution nothing is applied.
- But beware: Redis does not cancel individual commands if one fails after execution.
⚠️ Consistency
- Redis does not automatically enforce integrity constraints like relational databases.
- Consistency therefore depends on the application logic, not the Redis engine itself.
- In a relational database like PostgreSQL this is ensured by the schema you must follow to the letter to insert information.
✅ Isolation
- Redis executes the commands of a transaction sequentially and without interruption by other clients.
- This guarantees simple isolation, but not as fine as the isolation levels of relational DBMS.
⚠️ Durability
- Redis is an in-memory database, so data lives in RAM. In short, if there’s a crash your RAM is emptied and you lose everything.
- There are nevertheless modes that can improve durability, but of course they come at a cost:
- RDB (snapshot): periodic backups, risk of loss between snapshots.
- AOF (append-only file): better durability, but can be disabled or configured with delays.
- In case of a crash, some data may be lost if it hasn’t been written to disk.
When to use a traditional database?
✅ PostgreSQL/MySQL is perfect for:
- Persistent data: Everything that must survive a restart
- Complex relationships: JOINs, foreign keys, constraints
- Analytical queries: Aggregations, GROUP BY, complex calculations
- Large data: Several terabytes of data
- Data integrity: Complete ACID transactions
- Complete history: You never want to lose this data
The hybrid approach (the best!)
In reality, you will use both:
General principle:
- PostgreSQL = Source of truth, permanent data
- Redis = Speed layer, temporary or derived data
Example of using Redis
Here are several concrete examples of using Redis.
- Caching: Temporarily store data that is expensive to compute
Why? It avoids hammering PostgreSQL with the same queries. The result is in RAM, instantly retrievable.
- User sessions: Ephemeral data that must be ultra-fast
Why? Redis can handle thousands of session accesses per second without flinching. PostgreSQL would slow down with this ultra-frequent access pattern. Bonus: you can invalidate sessions instantly (logout everywhere).
- Real-time counters with delayed synchronization: Likes, views, live statistics
Why? Increment operations are atomic in Redis (no race conditions) and do not create any lock on PostgreSQL. You can absorb 10,000 increments per second without slowing down your main DB. PostgreSQL will keep only the final value.
- Job queues: With Sidekiq, for example
Why? Redis Lists offer ultra-fast LPUSH/RPOP atomic operations. PostgreSQL cannot beat this performance for high-frequency queues. Redis can handle millions of jobs per hour.
- Leaderboards and rankings: Perfect with Sorted Sets
Why? Redis Sorted Sets keep order automatically in O(log N) for the top N (1000 players). Perfect for showing leaders. For players outside the top, PostgreSQL takes over.
Important trade-off:
- ✅ Top 1000 in Redis: instant access, ultra-fast updates
- ✅ All players in PostgreSQL: full ranking available
- ⚠️ If you have 10 million players and put everything in Redis, you’ll consume a lot of RAM (avoid!).
- 💡 General rule: Redis for the "hot data" (top/active), PostgreSQL for the "cold data" (historic/complete)
- Real-time pub/sub: For ActionCable and WebSockets
Why? Redis Pub/Sub is non-blocking and can handle thousands of messages per second. PostgreSQL LISTEN/NOTIFY exists but isn’t designed for this throughput. Redis also enables horizontal scalability for your app (multiple Rails servers sharing the same Redis).
- Distributed rate limiting: Limiting API requests
Why? INCR + EXPIRE operations are atomic in Redis. No race conditions even with 10 Rails servers in parallel. PostgreSQL would have locking and performance issues with this access pattern.
|
Need
|
Redis
|
PostgreSQL
|
|---|---|---|
|
Pure Speed
|
⚡⚡⚡⚡⚡
|
⚡⚡⚡
|
|
Atomic Operations
|
⚡⚡⚡⚡⚡ (native)
|
⚡⚡⚡ (llocks required)
|
|
High-frequency writes
|
⚡⚡⚡⚡⚡
|
⚡⚡ (contention)
|
|
Guaranteed durability
|
⚡⚡ (optional)
|
⚡⚡⚡⚡⚡
|
|
Complex queries
|
⚡ (limited)
|
⚡⚡⚡⚡⚡
|
|
Relations
|
❌
|
⚡⚡⚡⚡⚡
|
|
Capacity
|
⚡⚡ (RAM limited)
|
⚡⚡⚡⚡⚡ (More Capacity HDD)
|
|
Cost
|
⚡⚡ (RAM expensive)
|
⚡⚡⚡⚡ (HDD Cheap)
|
Rails 8 and Redis: A New Era
Rails 8, released in 2024, introduced a major shift in the ecosystem: Solid Cache.
Solid Cache: The new paradigm
Solid Cache is an alternative to Redis for caching, using your database rather than memory. Surprising? Yes. Counterintuitive? Not so much!
The concept: with modern SSDs and in-memory caches built into databases, storing the cache on disk becomes viable. The upside? You can have a cache huge for a fraction of the RAM cost.
Basecamp numbers:
- Read requests 40% slower than with Redis
- But cache 6x larger!
- Result: 95th percentile response time dropped from 375ms to 225ms
Configuration in Rails 8:
By default, Rails 8 uses Solid Cache instead of Redis. It’s a pragmatic choice to simplify deployment.
So, is Redis dead in Rails 8?
- Absolutely not! Redis remains essential for:
- Cases where speed matters: Rate limiting, high-frequency sessions
- Special data structures: Sorted Sets for leaderboards
- Sidekiq: Always based on Redis for jobs
- ActionCable in production: Redis recommended for pub/sub
- Atomic counters: Ultra-fast increments
The right approach:
The dev container Rails 8
Important: Rails 8 no longer generates Redis by default in dev containers because it uses Solid Queue and Solid Cache. If you need Redis (for Sidekiq or others), add --skip-solid when creating the app:
Installation and configuration of Redis with Rails
Let’s get practical! Here’s how to install and configure Redis in your Rails project.
Step 1: Install Redis on your system
macOS (with Homebrew):
Ubuntu/Debian:
With Docker:
Step 2: Add the necessary gems
Step 3: Configure the Redis connection
Create an initializer for the global connection:
- Why the namespace? If you have multiple Rails apps using the same Redis, the namespace avoids key collisions. For example:
- Without namespace : user:1
- With namespace : my_app:production:user:1
Step 4: Configure Redis as a cache store
To use Redis as cache:
In development:
Step 5: Use Redis in your code
Basic cache:
Simple counter:
Set for tracking:
Leaderboard with Sorted Set:
Step 6: Configuration for Sidekiq (background jobs)
If you use Sidekiq for asynchronous jobs:
Patterns and Best Practices
Now that Redis is installed, here are patterns to know to use it effectively. Some examples are quite advanced. Don’t panic—you won’t have to implement them right away but it’s good to keep them in the back of your mind :)
1. Key naming: be structured!
Principle: use descriptive, hierarchical keys with : as a separator.
Recommended convention:
2. Automatic expiration: clean up after yourself
Always define a TTL (Time To Live) to prevent Redis from filling up:
Why is this crucial? Redis stores everything in RAM. Without expiration, you risk running out of memory. Expiring frees memory.
3. Atomic operations: be thread-safe
Redis guarantees atomicity of operations. Use it for counters!
4. Pipelining: batch operations
When you have several Redis commands to execute, use pipelining:
Performance gain: up to 10x faster for many operations!
5. Cache warming: preheat the cache
The problem of a "cold start":
Imagine your Redis app has just restarted (maintenance, crash, or simply first production). Your cache is empty.
Here’s what happens:
The first user experiences all the slowness while the cache fills. Then all other users benefit from the cache for 1 hour. But when the cache expires or Redis restarts, it’s back to square one: a user will bear the penalty.
The solution: Cache Warming
Rather than waiting for a user to trigger the calculation, proactively pre-warm the cache:
Exemple 1: Warming at application startup
Result: When the first user arrives, the cache is already warm. Response time: 5ms instead of 500ms!
Exemple 2: Periodic warming with Sidekiq-Cron
If your cache has a short TTL or some pages are very important, you can periodically pre-warm before expiration:
When to use cache warming?
✅ Use cache warming if:
- You have high-traffic pages with heavy queries
- Your Redis cache restarts regularly
- You want predictable response times
- Your queries take > 100ms to compute
- You have predictable peak moments (e.g., product launch)
❌ Do not use cache warming if:
- Your data changes constantly (real-time)
- You have low traffic (no benefit)
- Your queries are already fast (less than 50ms)
- You have too many data variations to pre-warm (millions of combinations)
Cache warming as a "performance assurance"
Think of cache warming as an insurance:
- Cost: a few background jobs (server resources)
- Benefit: a consistently fast user experience
- Optimal moment: just before cache expiration or after a restart
Analogy: It’s like preheating your oven before putting in the dish. You could wait for it to heat when you put the dish in (the user waits), or preheat it beforehand (the user is happy immediately).
6. Error handling: plan for outages
Redis can go down. Your app should not crash as a result:
For the Rails cache, error handling is built-in:
7. Monitoring: watch the metrics
Useful commands to monitor Redis:
In your Rails code:
8. Memory management: never forget the limit!
The problem: Redis stores EVERYTHING in RAM. If you fill memory, Redis crashes or starts rejecting commands.
You should start by setting a memory limit in Redis’s configuration
Eviction policies available:
- allkeys-lru : Removes the least recently used keys (recommended for cache)
- volatile-lru : Removes only keys with TTL
- allkeys-lfu : Removes least frequently used keys (Redis 4.0+)
- volatile-ttl : Removes keys with the shortest TTL
- noeviction : Rejects writes when full (dangerous!)
You can also limit the size of your collections
Memory usage monitoring
Managing hot data / cold data properly
Golden rules for memory:
- 📏 Always set maxmemory in production
- ⏱️ Always set TTLs on your keys
- 📊 Limit the size of collections (Lists, Sets, Sorted Sets)
- 🔍 Regularly monitor memory usage
- 🔥 Keep only the "hot data" in Redis
- 💾 Use PostgreSQL as the source of truth and archive
Practical cases: concrete examples
Let’s look at a few real implementations you’ll encounter often.
Example 1: Cache of expensive queries
Example 2: Rate limiting
Example 3: Game leaderboard
Example 4: Session store for authentication
Example 5: Pub/Sub for real-time notifications
Pitfalls to avoid
1. Forgetting that everything is in memory
Problem: Storing too much data without expiration consumes all RAM.
Solution: Always set TTLs and monitor memory usage.
2. Using Redis as the main database
Problem: Redis is not designed to replace PostgreSQL. Persistence isn’t its strong suit.
Solution: Use Redis as a complement, not a replacement.
3. Ignoring O(N) operations
Problem: Some commands are slow on large collections.
- Commands to avoid on large data:
- KEYS * (use SCAN instead)
- SMEMBERS on large sets (use SSCAN)
- HGETALL on large hashes (use HSCAN)
4. Not handling serialization
Problem: Redis stores strings. You should serialize complex objects.
5. Ignoring security
Problem: Redis by default has no authentication and listens on all interfaces.
Production solution:
SEO and performance optimization
Impact on SEO
- Redis indirectly improves your SEO by speeding up your site:
- Load time: Google favors fast sites
- Shorter response times = better ranking
- Cache of HTML fragments for instant pages
- Bounce rate: Faster site means users stay longer
- Less frustration
- More engagement
- Core Web Vitals: Redis helps improve key metrics
- LCP (Largest Contentful Paint): caches images and content
- FID (First Input Delay): faster response
- CLS (Cumulative Layout Shift): predictable loading
Example of a cache for SEO
Conclusion: Redis, your new performance ally
We’ve taken a full tour of Redis, from its fundamental concepts to its integration in Rails 8. Let’s recap what you should remember:
What Redis is:
- An in-memory, ultra-fast key-value database
- A versatile tool with rich data structures
- An essential complement to traditional databases
When to use Redis:
- ✅ Caching expensive data
- ✅ User sessions
- ✅ Real-time counters and statistics
- ✅ Leaderboards and rankings
- ✅ Job queues (Sidekiq)
- ✅ Rate limiting
- ✅ Pub/Sub for WebSockets
The Rails 8 ecosystem:
- Solid Cache by default to simplify deployment
- Redis still relevant for specific cases
- Hybrid approach recommended
Best practices:
- Name your keys in a structured way
- Always define expirations
- Use the appropriate data structures
- Handle errors gracefully
- Monitor memory usage
Redis isn’t magical, but it’s a powerful tool that, when used well, will transform the performance of your Rails application. Start small: add caching to a slow request, implement a simple counter, then gradually explore other possibilities.
Next steps:
- Install Redis locally and test the basic commands
- Add Redis caching to a slow page in your app
- Explore Sidekiq for asynchronous jobs
- Implement a leaderboard or a rate-limiting system
You now have all the keys (no pun intended 😉) to master Redis in your Rails projects. Happy coding!
