Eviction Policies

intermediate redis eviction lru lfu caching

When Redis’s memory usage hits the maxmemory limit, something has to go. The eviction policy decides what. There are eight options — most boil down to “evict by recency, by frequency, by TTL, or randomly”.

In simple language — think of it like a small fridge. When it’s full and you want to put in a new item, you have to throw something out. Do you toss the oldest? The least-eaten? Or just grab whatever’s in front?

Setting it up

CONFIG SET maxmemory 2gb
CONFIG SET maxmemory-policy allkeys-lru

Or in redis.conf:

maxmemory 2gb
maxmemory-policy allkeys-lru

If you don’t set maxmemory, Redis will grow until the OS kills it (OOM). Always set it in production.

The eight policies

Eviction policies grouped by behavior
noeviction
Refuse new writes with OOM error. Reads still work.
allkeys-lru / lfu / random
Evict from any key in the dataset.
volatile-lru / lfu / random / ttl
Only evict from keys that have a TTL set.

The full list:

PolicyWhat it evicts
noevictionNothing — new writes fail when full
allkeys-lruLeast Recently Used, any key
allkeys-lfuLeast Frequently Used, any key
allkeys-randomA random key
volatile-lruLRU, but only keys with TTL
volatile-lfuLFU, but only keys with TTL
volatile-randomRandom key with TTL
volatile-ttlThe key closest to expiring

LRU vs LFU — what’s the difference?

LRU (Least Recently Used) — kicks out the key that hasn’t been touched in the longest time. Good when “recent = important”. A user who hit the site 1 minute ago probably matters more than one who hit it yesterday.

LFU (Least Frequently Used) — kicks out the key that’s been touched the fewest times overall. Good when popularity matters more than recency. A homepage hit 10000 times shouldn’t get evicted just because nothing touched it in the last 5 seconds.

LRU vs LFU on the same access pattern
Access log:  A A A A A A B C D E
                 (A hit 6 times, then B C D E one each)

LRU evicts: A ← A is oldest, even though it’s hottest LFU evicts: B ← B has been touched only once

LRU is an approximation in Redis — it samples a few keys and evicts the least recent. Same for LFU. Not exact, but cheap and good enough. Tune via maxmemory-samples (default 5, higher = more accurate, more CPU).

When to use which

Pure cache, no TTLs, hot-cold access:
→ allkeys-lru   (default-ish good choice)

Pure cache, popularity-driven (e.g. trending content):
→ allkeys-lfu

Mixed dataset: some keys are "real data", some are cached with TTLs:
→ volatile-lru or volatile-lfu
   (protects the no-TTL keys, only evicts the explicitly-cached ones)

Redis as a job queue or session store you can't afford to lose:
→ noeviction
   (let it OOM and alert you — better than silent data loss)

Don't care, just keep it running:
→ allkeys-random  (rarely the right choice, but cheapest)

Inspecting evictions

INFO stats | grep evicted
# evicted_keys:12047
# evicted_clients:0

INFO memory | grep maxmemory
# maxmemory:2147483648
# maxmemory_policy:allkeys-lru

If evicted_keys is climbing fast, your cache is too small for the working set — either bump maxmemory or shrink your data (better compression, shorter TTLs, drop hot-but-useless fields).

A subtle thing — noeviction is the default. If you set maxmemory but forget the policy, writes will start failing once you hit the limit. Always set both explicitly.