Redis does not manage memory for you. You set a maxmemory limit, choose an eviction policy, and Redis enforces both mechanically. Skip those settings and Redis will grow until the OS kills it, reject every write when the limit is hit, or silently evict keys you expected to stay cached. That is not a tuning detail — it is the difference between a cache that degrades gracefully and one that breaks applications under load.

Situation

A typical Redis cache deployment sets keys with TTLs, adds a maxmemory directive, and moves on. The assumption is that Redis will handle the rest.

Redis exposes eviction policy as an explicit operator decision because different workloads have different requirements for which keys are safe to drop. A session store, a product catalog cache, and a rate-limiter all need different behavior at the eviction boundary. Redis gives you control, but that control requires a deliberate choice.

The Problem

The failure modes appear only under sustained write pressure. When maxmemory is not set, Redis accepts all writes until the host runs out of memory and the OOM killer terminates the process. When noeviction is set and the limit is reached, Redis returns OOM command not allowed when used memory > 'maxmemory' on every write. When volatile-lru is configured but no keys have TTLs, Redis cannot find eligible keys and silently falls back to noeviction behavior.

Which policy fits your workload, and where does each one fail?

How Eviction Works

When a write arrives and memory is at the limit, Redis runs eviction logic before accepting the write. The policy determines which key is dropped.

Redis 7.x documents eight policies:

PolicyKey poolAlgorithmUse case
noevictionRejects writesPersistent stores where data loss is unacceptable
allkeys-lruAll keysLeast recently usedGeneral-purpose cache
volatile-lruTTL keys onlyLRU from TTL setMixed store where permanent keys must survive
allkeys-lfuAll keysLeast frequently usedSkewed access patterns with a hot key set
volatile-lfuTTL keys onlyLFU from TTL setMixed store with skewed access
allkeys-randomAll keysRandomAlmost never correct in production
volatile-randomTTL keys onlyRandom from TTL setRarely useful
volatile-ttlTTL keys onlyShortest TTL firstWhen expiry order should drive eviction

For a standard cache where all keys have TTLs and access is roughly uniform, allkeys-lru is the documented starting recommendation in the Redis memory management documentation. It requires no TTL discipline and evicts based on recency.

For workloads with a stable hot key set — recommendations, trending content, rate-limit counters — allkeys-lfu is a better fit. LFU tracks frequency rather than recency, so a hot key accessed hundreds of times will not be dropped for being idle. LFU support arrived in Redis 4.0.

One detail matters for both: Redis does not maintain a true LRU or LFU data structure. It samples maxmemory-samples keys (default: 5) and evicts the best candidate from that sample. This is an approximation; larger sample sizes improve accuracy at the cost of CPU.

Set the policy in redis.conf or apply it at runtime without a restart:

# redis.conf — set once, survives restart
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 10
# Apply at runtime without restart
redis-cli CONFIG SET maxmemory-policy allkeys-lru
redis-cli CONFIG SET maxmemory-samples 10

The volatile-* policies only touch keys with a TTL set. If the application writes any keys without TTLs, those keys are never eligible for eviction. As non-TTL keys accumulate, the eviction pool shrinks, and under write pressure Redis exhausts eligible keys and falls back to noeviction behavior without any configuration change.

In Practice

The Redis eviction policies reference at redis.io explicitly documents the noeviction fallback when volatile-* policies find no eligible keys. This is designed behavior. The practical consequence: volatile-lru is safe only when TTL discipline is enforced at the application layer, not assumed.

For diagnosis, INFO memory returns mem_fragmentation_ratio. The Redis documentation flags ratios above 1.5 as significant — the process RSS exceeds what Redis counts as used_memory. Eviction uses used_memory, not RSS, so high fragmentation means the host can approach OOM before Redis triggers any eviction.

Where It Breaks

ScenarioWhat breaksWhy
volatile-lru with no TTL keysWrites fail under load; Redis behaves as noevictionEviction pool is empty; documented Redis fallback behavior
LRU or LFU with maxmemory-samples 5Hot keys can be evicted by chanceRedis samples 5 keys, not the full keyspace; approximation only
High mem_fragmentation_ratio with tight maxmemoryRSS exceeds RAM before eviction triggersEviction uses used_memory, not RSS; fragmentation is invisible to eviction logic

What to Do Next

  • Problem: Unset or mismatched eviction policy causes write failures, hit-rate degradation, or OOM kills under load.
  • Solution: Set maxmemory explicitly; use allkeys-lru for general caches, allkeys-lfu for skewed workloads; avoid volatile-* unless TTL discipline is enforced at the application layer.
  • Proof: After a load test, redis-cli INFO stats | grep evicted_keys should be non-zero and used_memory should stay below maxmemory.
  • Action: Run redis-cli CONFIG GET maxmemory && redis-cli CONFIG GET maxmemory-policy across production instances; any instance returning 0 for maxmemory is unprotected.

Eviction policy is one of the few Redis settings where the wrong default does not produce an immediate visible failure — it surfaces only when the cache fills up, which is exactly when you need it most.