You're obsessing over cache hit ratios, tweaking TTLs, and purging like a maniac—but I bet you've never looked at your Redis eviction policy. That's the first mistake. Most teams default to noeviction or volatile-lru and then wonder why their cache is useless. Here's the blunt truth: for a typical web app, you should be using allkeys-lru. It's not just a setting; it's the difference between a cache that absorbs 70-90% of your database load and one that's a glorified sticker board.
This is for anyone running Redis in front of a relational database, especially if you're using cache-aside (lazy loading) and are tired of waking up to database CPU alerts. I'm going to walk you through the exact steps to tune your eviction policy, and I'll show you why volatile-ttl is a trap for most people. We'll also touch on when to break the rules. No fluff—just a numbered walkthrough.
1. Check Your Current Eviction Policy
First, log into your Redis instance and run CONFIG GET maxmemory-policy. If it says noeviction, your cache is a ticking time bomb: when memory fills, writes start throwing errors, and your app starts failing in weird ways. If it says volatile-lru, you're only evicting keys that have a TTL set—which means any key you forgot to add an expiration to is immortal and will eat your memory until the OOM killer shows up. The fix is simple: set it to allkeys-lru. This tells Redis to evict the least recently used key across the entire keyspace, not just the ones with expirations (Redis docs). That's what a cache is for—it's not storage, so don't treat it like one (AWS). With allkeys-lru, Redis will automatically drop the least-used data when memory is tight, keeping your hot data fresh and your cache useful.
2. Understand the Eviction Alphabet Soup
Redis gives you a ton of eviction policies: allkeys-lru, allkeys-lfu, volatile-lru, volatile-ttl, noeviction, and a few more (Redis docs). The key distinction is between allkeys-* and volatile-*. The former evicts any key; the latter only evicts keys that have a TTL. If you're using volatile-*, you're betting that every important key has an expiration set. But in practice, you'll have some keys without TTLs—like config data or session tokens—and those will never get evicted, so they'll sit there forever, bloating memory. allkeys-lru avoids that by treating the whole keyspace as fair game. LFU (least frequently used) is another option, and it can give better hit rates than LRU in some cases (Redis docs), but it's more complex to reason about. Start with LRU; it's the default recommendation because it's simple and effective (AWS).
3. Watch Out for the volatile-ttl Trap
I see people gravitate to volatile-ttl because they think it's smart—it evicts keys with the shortest remaining TTL, so you're getting rid of data that's about to expire anyway. But here's the catch: if you have any keys without a TTL, they're never evicted. And if your cache is mostly keys with long TTLs (like a week), volatile-ttl will evict the short-lived keys first, which might be your hot data. A classic mistake is setting a short TTL on frequently accessed items (like user sessions) and a long TTL on rarely accessed static data. Under pressure, Redis evicts the short-TTL keys, which are your hot items, and your cache hit ratio tanks. Meanwhile, allkeys-lru would evict the cold static data and keep the hot sessions. Which would you rather have? The answer is obvious.
4. Set It and Forget It (Almost)
Once you've switched to allkeys-lru, you need to make sure it sticks. In your Redis config file, set maxmemory-policy allkeys-lru and also set a maxmemory value that's high enough to hold your working set but low enough to leave headroom for the OS. If you're using a managed service like ElastiCache, you can set it via parameter group. Then, monitor your evicted_keys metric. If you see a lot of evictions, that's fine—it means Redis is doing its job. But if you see a lot of evictions and your hit ratio is low, you might need to increase memory or look at your access patterns. Also, consider using Redis's persistence options: you can disable persistence entirely if you're using Redis as a pure cache, because a cache doesn't need to survive restarts (Redis docs). That'll save you disk I/O and improve performance.
Here's a quick tip: if you're using SETEX to set keys with TTLs, remember that SETEX is equivalent to SET key value EX seconds (Redis docs). It's a single atomic command, so use it instead of separate SET and EXPIRE calls to avoid race conditions.
What Can Go Wrong
The biggest risk with allkeys-lru is that you might evict a key that you didn't expect to be evicted—like a counter you're incrementing with INCR. If that key gets evicted, you lose the count. That's fine if it's just a hit counter, but if it's something like a rate limiter, you might let too many requests through. So, if you have keys that must never be lost, don't store them in Redis as a cache—use a separate Redis instance with noeviction or use a database. Also, be aware that changing your eviction policy can cause a thundering herd the first time you deploy, because the cache is cold and all requests hit the database. To avoid that, you can pre-warm your cache or use stale-while-revalidate (RFC 5861) to serve stale data while you revalidate.
Bottom Line
Stop tweaking TTLs and purging manually—the single best move you can make is to set your Redis eviction policy to allkeys-lru. It's the difference between a cache that actually reduces database load by 70-90% and one that's just eating memory. Do it today.
Sources
- Redis (eviction) - https://redis.io/docs/latest/develop/reference/eviction/
- AWS (caching overview) - https://aws.amazon.com/caching/
- RFC 5861 (stale-while-revalidate) - https://www.rfc-editor.org/rfc/rfc5861.txt
- Redis (SETEX) - https://redis.io/docs/latest/commands/setex/
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!