Your cache hit rate is 99% and your app is still slow. Before you blame your queries or your indexes, run this:

redis-cli INFO stats | grep evicted_keys

If that number is climbing, your eviction policy is the problem — not your code.

The Default That Will Ruin Your Day

Redis ships with noeviction as the default maxmemory-policy. Under memory pressure, it does not quietly make room. It returns an error and refuses to accept new writes. Your app does not degrade gracefully. It crashes.

The reason most engineers miss this is that evicted_keys is not in the standard dashboard. It lives in INFO stats, a section most people never look at. Meanwhile, the hit rate metric continues to look healthy because Redis is still serving reads from whatever keys remain. The writes are failing silently.

The Fix

Two commands:

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

Set an explicit maxmemory — never leave it at the default of zero, which means unlimited and lets Redis consume all available system memory until the OS kills it. Then pick a policy that matches your workload.

The Four Policies Worth Knowing

noeviction — the default. Returns errors on write when memory is full. Only appropriate when you control memory precisely and want Redis to protect its data at all costs rather than silently discard it. In most caching scenarios this is the wrong choice.

allkeys-lru — evicts the least recently used key across all keys, regardless of TTL. This is the right default for general-purpose caching. The keys your application accesses most frequently stay hot; stale entries get evicted first.

volatile-lru — same as allkeys-lru but only considers keys that have a TTL set. Useful when Redis is doing double duty as both a cache and a persistent store. Persistent keys without a TTL are never evicted; only TTL-bearing cache keys are eligible.

allkeys-lfu — evicts the least frequently used key, available since Redis 4.0. Better than LRU when you have a small set of very hot keys that should never be evicted regardless of recency. A key that gets hit a thousand times a day but not in the last hour will survive under LFU; it might not under LRU.

Reading the Signal Correctly

The hit rate metric is calculated as keyspace_hits / (keyspace_hits + keyspace_misses). It tells you what percentage of read attempts found a key. It says nothing about whether keys were evicted before being read, whether write errors were swallowed by application code, or whether your total available keyspace is shrinking.

evicted_keys in INFO stats tells you how many keys Redis has discarded to make room. In steady state, this number should be zero. If it is climbing, you are silently losing data while your hit rate dashboard looks perfectly healthy.

Add evicted_keys to your observability setup alongside hit rate. Watch both together. A rising eviction count alongside a high hit rate is a warning sign — it means your cache is under memory pressure and your metrics are masking it.

Putting It Into Practice

redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy
redis-cli INFO stats | grep evicted_keys
redis-cli INFO memory | grep used_memory_human

If maxmemory is 0 or maxmemory-policy is noeviction, fix it before you hit production load. The changes take effect immediately without a restart and persist across connections.

If you’re on a managed Redis provider like Upstash, these settings are controlled through the provider console. Check your plan’s memory limit and confirm the eviction policy is set explicitly — do not assume the provider default is appropriate for your workload.

The five minutes it takes to add evicted_keys to your dashboard and set an explicit eviction policy is the cheapest insurance you can buy on a cache-dependent service.

Frequently Asked Questions

What is the default Redis eviction policy and what are its risks?

The default Redis eviction policy is noeviction, which means Redis returns an error on write operations when memory is full rather than removing any keys. This causes applications to crash or degrade ungracefully under memory pressure, and because reads still succeed, cache hit rate metrics can appear healthy while writes are silently failing.

What is the difference between allkeys-lru and volatile-lru in Redis?

allkeys-lru evicts the least recently used key from any key in the database regardless of TTL, making it suitable for pure caching workloads. volatile-lru applies the same LRU logic but only to keys that have a TTL set, which protects persistent keys without expiration — the right choice when Redis serves as both a cache and a persistent data store simultaneously.

How do I check if Redis is evicting keys and causing performance problems?

Run ‘redis-cli INFO stats | grep evicted_keys’ and monitor whether the value is increasing over time. A rising evicted_keys count indicates Redis is under memory pressure and actively removing keys, which can cause cache misses and application slowdowns even when the overall hit rate metric looks acceptable.

What Redis maxmemory-policy should I set for a general-purpose cache?

For most general-purpose caching scenarios, set maxmemory-policy to allkeys-lru using ‘redis-cli CONFIG SET maxmemory-policy allkeys-lru’. Also set an explicit maxmemory limit such as ‘redis-cli CONFIG SET maxmemory 2gb’ to prevent Redis from consuming all available system memory, which can cause the OS to kill the process.