Redis Eviction Policy Guide: Choosing maxmemory-policy
Redis eviction policy explained: how maxmemory-policy works under sustained load, which of 8 options to pick, and how to avoid silent data loss in production.
Redis eviction policy explained: how maxmemory-policy works under sustained load, which of 8 options to pick, and how to avoid silent data loss in production.
The exact query engineers type into a search bar at 2 a.m. is usually some version of "redis eviction policy production" or "why is redis dropping my keys." The short answer: Redis only evicts keys because you told it to, either explicitly through maxmemory-policy or implicitly by leaving the default noeviction in place until writes start failing. Which of the eight policies is right for your service depends on whether Redis is a pure cache, a session or queue store, or a mix of both — and that answer changes again once traffic is sustained rather than bursty. This guide walks through the mechanics, the trade-offs, and a rollout checklist you can apply to a production cluster this week.
Redis ships with maxmemory-policy set to noeviction. That is not a safe default for most SaaS workloads — it means once used_memory reaches maxmemory, Redis rejects every write command that would consume more memory (SET, LPUSH, HSET, SADD, and friends) with an OOM error, while reads keep working. If your application does not catch that error explicitly, a checkout flow, a session write, or a queue enqueue silently fails at exactly the moment traffic is highest, because that is when memory pressure peaks. Teams who never touch maxmemory-policy usually discover this the same way: a spike in 500s that correlates with a memory graph flatlining at the ceiling, not with CPU or network.
Eviction policies exist to make that failure mode a deliberate choice instead of an accident. Instead of rejecting the write, Redis frees space by deleting existing keys according to the policy you configure, then completes the write. The trade-off is explicit: you are choosing to lose some data to keep the service available, and the policy determines which data you lose first.
| Policy | What it evicts | Best for |
|---|---|---|
| noeviction | Nothing — rejects writes at the memory ceiling | Redis as a system of record you cannot afford to lose (rare) |
| allkeys-lru | Least recently used key, any key | Pure cache in front of a database, unsure traffic pattern |
| allkeys-lfu | Least frequently used key, any key | Cache with a stable power-law access pattern (hot/cold split) |
| allkeys-random | Random key, any key | Uniform access patterns where recency/frequency carry no signal |
| volatile-lru | Least recently used key, only keys with a TTL | Mixed instance: some keys must survive, cache keys can go |
| volatile-lfu | Least frequently used key, only keys with a TTL | Mixed instance, frequency-based cache portion |
| volatile-random | Random key, only keys with a TTL | Mixed instance, cheapest CPU cost, weak hit-rate signal |
| volatile-ttl | Key closest to expiring, only keys with a TTL | Mixed instance where near-expiry keys are safest to drop early |
In practice, production traffic settles on two policies almost every time. If the Redis instance is exclusively a cache — API responses, rendered fragments, computed aggregates — allkeys-lru is the pragmatic default: it needs no per-key TTL bookkeeping, it is memory-efficient because you do not pay the ~8 extra bytes per key for an expiry field on every entry, and it degrades gracefully under a typical Zipfian (power-law) access pattern where a small set of keys absorbs most of the traffic. If the same instance also holds session tokens, rate-limit counters, or queue metadata that must not be evicted, volatile-lru with TTLs set only on the cache keys keeps the durable keys off the eviction table entirely, because volatile- policies never touch keys without an expiry.
Eviction policy choices that look fine in staging often break down under weeks of sustained production traffic for three reasons. First, LRU in Redis is approximated, not exact — by default Redis samples 5 keys (maxmemory-samples) and evicts the oldest of that sample, which is cheap but means true "least recently used" accuracy degrades as your keyspace grows into the tens of millions. Raising maxmemory-samples to 10 improves accuracy at a small CPU cost and is worth it once a single node holds more than a few million keys under real eviction pressure. Second, memory fragmentation compounds over time: Redis's allocator (jemalloc by default) can leave used_memory reporting well below what the OS actually has resident, so mem_fragmentation_ratio creeping toward 1.5 or higher under sustained load means eviction is being triggered later than it should, or not accurately reflecting real headroom — that is a signal to schedule a rolling restart or upgrade Redis, not to loosen the eviction policy further. Third, sustained load exposes hot keys: a policy tuned for an even distribution will thrash if 1% of keys take 90% of traffic, because LRU eviction and the active-expire cycle both compete for CPU with the read/write load on those same hot keys, adding latency spikes exactly when you can least afford them.
The practical fix for hot-key thrash under an eviction policy is usually smaller and shorter-lived cache entries with jittered TTLs (so keys do not all expire in the same millisecond and stampede the origin), not a different eviction algorithm. Combine that with client-side caching (RESP3 tracking) for the hottest handful of keys so Redis is not even asked for them on every request.
Every eviction policy other than noeviction is, by definition, deleting data your application did not ask to delete. The only way to know whether that is happening at an acceptable rate is to watch it directly rather than infer it from error rates.
“Eviction policy is not a set-and-forget config line. It's a promise about which data your system is allowed to lose under pressure — and that promise should be tested the same way you test failover, not discovered during an incident.”
None of this replaces the broader scaling work — sharding, replica topology, connection pooling — that keeps a Redis cluster healthy as traffic grows; eviction policy is one layer of that stack, and it's often the layer teams configure once during setup and never revisit as data volume and traffic pattern change underneath it.
Eviction policy is just one piece of running Redis reliably at scale. See how the rest of the stack — clustering, hot keys, and persistence trade-offs — fits together.
Read: Scaling Redis for High-Traffic SaaSallkeys-lru is the safest default for a pure cache: it requires no per-key TTL management, is memory-efficient, and handles the power-law access pattern most caches see. Switch to allkeys-lfu only if your data shows a stable long-tail that LRU evicts too slowly, and verify the switch with a hit-rate comparison under real traffic.
Because the default maxmemory-policy is noeviction. Redis will not delete data on your behalf unless you explicitly opt into a different policy, since deleting data is a business decision, not a purely technical one. Most production caches should not run on noeviction.
Not per-key, but volatile- policies only evict keys with a TTL set, so you can protect session or queue keys by never setting an expiry on them while letting cache keys carry a TTL and evict freely. For stricter isolation, separate cache and durable data into different Redis instances or logical databases.
Watch the evicted_keys rate alongside keyspace_misses and used_memory as a percentage of maxmemory. A rising eviction rate combined with rising cache misses means your working set has outgrown available memory and needs more capacity, not just a policy change.
Yes. Redis approximates LRU/LFU by sampling a small number of keys (5 by default) and evicting the oldest of that sample. Raising maxmemory-samples to 10 gets closer to true LRU behavior at a modest CPU cost, which matters once a node holds several million keys under sustained eviction pressure.
Running Redis under production load and not sure your eviction and memory strategy will hold at 10x traffic? Fepiq designs and audits Redis architecture for growing SaaS teams.
Talk to Fepiq about your Redis architectureOccasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.
Keep reading
How to scale Redis under sustained load: eviction policies, hot keys, AOF vs RDS persistence, and clustering explained for growing SaaS teams.
tRPC vs REST for a TypeScript SaaS backend in 2026: when end-to-end type safety wins, when you still need REST, and the hybrid pattern most production apps use.
Let's build something
Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.