🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Redis Running Out of Memory and Evicting Keys — How to Actually Fix It

Redis is hitting maxmemory and evicting keys you didn't expect to lose, or refusing writes entirely. Here's how to diagnose which eviction policy is wrong for your use case and fix it properly.

DevOpsBoysJun 18, 20264 min read
Share:Tweet

Redis hitting its memory ceiling shows up two ways: either it starts evicting keys silently (data just disappears, no error), or it starts refusing writes outright with OOM command not allowed. Both point to the same root cause, but the fix depends on which one you're seeing and why.

Step 1: Confirm What's Actually Happening

bash
redis-cli INFO memory
used_memory_human:3.95G
maxmemory_human:4.00G
maxmemory_policy:noeviction
evicted_keys:0

If maxmemory_policy is noeviction and you're near the ceiling, Redis will start rejecting writes rather than silently dropping data — that's the OOM command not allowed error. If the policy is anything else (allkeys-lru, volatile-lru, etc.), check evicted_keys — a rapidly growing number means Redis is actively deleting data to stay under the limit, silently.

bash
redis-cli INFO stats | grep evicted_keys
# Run twice, a minute apart — if the number is climbing, eviction is active right now

Step 2: Pick the Right Eviction Policy for Your Actual Use Case

This is where most misconfigurations live — Redis ships with noeviction as default, which is correct for some workloads and catastrophic for others.

noeviction        → Refuses writes when full. Correct if Redis holds data you 
                     CANNOT lose (primary data store, not just a cache).

allkeys-lru       → Evicts least-recently-used keys, regardless of TTL. 
                     Correct for pure caching where everything is disposable.

volatile-lru      → Only evicts keys that have a TTL set, LRU order. 
                     Correct if you mix cache data (with TTL) and 
                     session/state data (no TTL) you can't afford to lose.

allkeys-lfu       → Evicts least-frequently-used. Better than LRU for caches 
                     with strong "hot key" patterns (some keys accessed 
                     constantly, most rarely).

volatile-ttl      → Evicts keys with the shortest remaining TTL first.
bash
# Check current policy
redis-cli CONFIG GET maxmemory-policy
 
# Set the correct one for your use case — this takes effect immediately, no restart
redis-cli CONFIG SET maxmemory-policy allkeys-lru

The most common real-world mistake: using Redis as both a cache (disposable, fine to evict) and a session store (must not be evicted) in the same instance with allkeys-lru. This silently evicts active user sessions under memory pressure. Fix: either separate them into different Redis instances/databases, or use volatile-lru and make sure session keys have no TTL while cache keys do — but this conflates "no TTL = protected" with "permanent," which isn't guaranteed under volatile-lru either if you genuinely run out of room. The safest fix is separate instances.

bash
# Run two logical Redis instances on separate ports — cheap insurance 
# against this exact class of bug
# redis-cache.conf
port 6379
maxmemory 2gb
maxmemory-policy allkeys-lru
 
# redis-sessions.conf  
port 6380
maxmemory 1gb
maxmemory-policy noeviction

Step 3: Find What's Actually Consuming Memory

Sometimes the real fix isn't the eviction policy — it's that something is using far more memory than it should.

bash
# Sample key sizes by pattern to find memory hogs
redis-cli --bigkeys
 
# Or for a more targeted look at memory by key pattern
redis-cli --memkeys --memkeys-samples 1000
Biggest hash found 'user:session:bulk_cache' has 4,200,000 fields
Biggest string found 'analytics:daily:2026-06-17' has 89,400,320 bytes

A single oversized key (an analytics blob that should be in a proper datastore, not Redis) is a more common root cause than "we just need more memory" — check this before reaching for a bigger instance.

Step 4: If You Genuinely Need More Capacity

bash
# Check current limit and actual server capacity
redis-cli CONFIG GET maxmemory
free -h
bash
# Raise the limit — but leave real headroom for Redis's own overhead 
# (replication buffers, client output buffers, fragmentation)
redis-cli CONFIG SET maxmemory 6gb
# On a machine with 8GB RAM, this leaves the OS and Redis overhead 2GB — 
# tight but workable. Don't set maxmemory close to total system RAM.
bash
# Make this permanent in redis.conf, not just runtime config 
# (CONFIG SET doesn't survive a restart)
echo "maxmemory 6gb" >> /etc/redis/redis.conf
echo "maxmemory-policy allkeys-lru" >> /etc/redis/redis.conf

Monitoring So You Catch This Before It's a Production Incident

yaml
- alert: RedisMemoryNearLimit
  expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.85
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: "Redis memory usage above 85% of maxmemory for 10m"
 
- alert: RedisEvictingKeysRapidly
  expr: rate(redis_evicted_keys_total[5m]) > 100
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Redis is evicting more than 100 keys/sec — check if this is expected"

The second alert matters even if eviction is your intended behavior — a sudden spike in eviction rate usually means something changed (a new feature writing way more keys, a TTL misconfiguration, a cache stampede) and is worth investigating even when "eviction is normal" for your setup.

Compare against alternatives if Redis memory limits are a recurring fight: Redis vs Dragonfly vs KeyDB

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments