NoSQL Databases

Redis Memory Optimization: Encoding, TTLs, and Eviction Policies

Redis hit maxmemory and evicted your session keys because the application stored 8KB JSON blobs instead of 200-byte hashes. Learn to audit memory usage, use compact encodings, and configure the right eviction policy.

JusDB Team
January 17, 2025
8 min read
165 views

Redis hit maxmemory at 3 AM and started evicting your session keys. Users were logged out. The fix wasn't more RAM — it was discovering that your application was storing 8KB JSON blobs when 200-byte hashes would do the same job. Here's how to audit, optimize, and right-size Redis memory usage.

TL;DR
  • Use MEMORY USAGE key and redis-cli --bigkeys to find oversized keys
  • Hashes, lists, and sets with small counts use compact ziplist/listpack encoding — 5–10x smaller than individual strings
  • Always set TTLs on non-permanent keys — missing TTLs are the #1 cause of unbounded Redis growth
  • Choose the right maxmemory-policy for your workload: allkeys-lru for caches, noeviction for session stores

Finding Memory Hogs

Top-Level Memory Report

bash
# Connect and check overall memory
redis-cli INFO memory

# Key fields:
# used_memory_human:        how much Redis is using
# used_memory_peak_human:   peak usage
# mem_fragmentation_ratio:  ideal ~1.0-1.5; high = wasted memory from fragmentation
# maxmemory_human:          your configured limit

# Find big keys (scans entire keyspace -- run on replica)
redis-cli --bigkeys
# Shows: top 10 largest keys per data type

# More detailed: sample 1% of keys
redis-cli --memkeys --memkeys-samples 100

Inspect Individual Key Memory

bash
# Memory used by a single key (including overhead)
redis-cli MEMORY USAGE user:session:abc123
# Returns bytes; typical small hash: 200-400 bytes

# Check encoding of a key
redis-cli OBJECT ENCODING user:session:abc123
# Compact encodings: ziplist, listpack, intset, embstr
# Expensive encodings: hashtable, skiplist, raw

# Debug object details
redis-cli DEBUG OBJECT user:session:abc123

Encoding Optimization: The Big Win

Store Sessions as Hashes, Not JSON Strings

python
import redis
import json

r = redis.Redis()

# BAD: store session as JSON string
# Memory: ~500 bytes per session (JSON overhead + string key)
r.set('session:abc123', json.dumps({
    'user_id': 42, 'role': 'admin', 'cart': [1, 2, 3], 'ip': '1.2.3.4'
}))

# GOOD: store session as Hash
# Memory: ~150 bytes per session (hash with ziplist encoding)
r.hset('session:abc123', mapping={
    'user_id': 42, 'role': 'admin', 'ip': '1.2.3.4'
})
r.expire('session:abc123', 3600)  # always set TTL!

# Even better: store cart separately with its own TTL
r.rpush('cart:42', 1, 2, 3)
r.expire('cart:42', 86400)

Keep Hashes in Compact Encoding

bash
# Hash uses ziplist/listpack (compact) when:
# field count <= hash-max-listpack-entries (default: 128)
# field value size <= hash-max-listpack-value (default: 64 bytes)

# redis.conf tuning for small hashes:
hash-max-listpack-entries 128
hash-max-listpack-value   64

# Verify encoding stays compact:
redis-cli OBJECT ENCODING session:abc123
# Should return: listpack (or ziplist on older Redis)
# NOT: hashtable (which uses 5-10x more memory)

Eviction Policy Configuration

bash
# Set maxmemory and eviction policy
redis-cli CONFIG SET maxmemory 8gb
redis-cli CONFIG SET maxmemory-policy allkeys-lru

# Eviction policies:
# noeviction    -- return errors when full (use for session/queue stores)
# allkeys-lru   -- evict least recently used (best for pure caches)
# volatile-lru  -- evict LRU keys with TTL set (mixed workloads)
# allkeys-lfu   -- evict least frequently used (Redis 4+, better for skewed access)
# volatile-ttl  -- evict keys closest to expiry

# Persist to redis.conf
# maxmemory 8gb
# maxmemory-policy allkeys-lru
Warning

Using noeviction when Redis hits maxmemory causes all write commands to return OOM command not allowed errors. Your application must handle this gracefully. Use noeviction only for session and queue stores where losing data is worse than returning errors.

Key Takeaways
  • Store structured data as Redis Hashes (not JSON strings) to use ziplist/listpack encoding — typically 5–10x smaller memory footprint.
  • Run redis-cli --bigkeys on replicas monthly to identify oversized keys before they exhaust maxmemory.
  • Set TTLs on every non-permanent key — missing TTLs are the most common cause of unbounded Redis growth.
  • Choose allkeys-lru for pure cache workloads and noeviction for session stores where data loss is unacceptable.

Working with JusDB on Redis Optimization

JusDB audits Redis memory usage for engineering teams, identifies encoding inefficiencies, and implements TTL policies that right-size Redis deployments without hardware upgrades. We have consistently reduced Redis memory consumption by 40–70% through encoding and data model optimization.

Explore JusDB Redis Services →  |  Talk to a DBA

Share this article

JusDB Team

Official JusDB content team