Redis eviction policies define what the server does when memory reaches the configured maxmemory limit. The policy can reject new writes or remove existing keys according to recency, frequency, expiration, or random selection.
For production applications, eviction is not only a cache-tuning setting. It is a data-loss policy for whatever roles share that Redis-compatible instance. A policy that works well for disposable cache entries can be dangerous for sessions, locks, queues, or rate-limit state.
This guide owns Redis eviction and memory-policy selection. For persistence, use Redis Persistence Explained: RDB, AOF, and Data Loss Trade-Offs. For broader cache/queue architecture, use Redis Cache Strategy for SaaS Apps.
Eviction begins only after a memory limit is reached
Redis can be configured with a maxmemory limit. When memory use reaches that limit, the configured maxmemory-policy determines the next action.
The practical choices fall into two groups:
| Policy family | Behavior | Best fit |
|---|---|---|
noeviction | Reject writes that require more memory | State that must not be silently discarded |
allkeys-* | Any key can be selected for eviction | Dedicated cache instances |
volatile-* | Only keys with TTL/expiry can be evicted | Mixed workloads where expiring keys are intentionally disposable |
Within the eviction families, Redis supports LRU, LFU, TTL-based, and random selection strategies.
The important first question is not LRU versus LFU. It is which keys are allowed to disappear at all.
allkeys-lru is a strong general cache default
LRU means Least Recently Used. Redis approximates LRU rather than maintaining a perfectly ordered list of every key.
allkeys-lru can work well when:
- the instance is dedicated to rebuildable cache;
- recently accessed keys are more likely to remain useful;
- keys do not all have carefully managed TTLs;
- cache misses can safely fall back to a durable source.
Example:
hot customer profile → accessed repeatedly → likely retained old dashboard result → not used recently → more likely evicted
This is a reasonable general-purpose strategy for many caches, but it should not be used blindly on instances that also store queue jobs, durable session state, or locks.
LFU favors frequently reused keys
LFU means Least Frequently Used. It tracks approximate access frequency and tends to retain keys used repeatedly over time.
allkeys-lfu can outperform an LRU-style policy when a small set of items is consistently popular while one-off scans should not displace them.
Typical cases include:
- popular product metadata;
- frequently requested API responses;
- configuration shared across many requests;
- catalog or permission data with stable hot sets.
The distinction is useful:
LRU asks: “what was used recently?” LFU asks: “what is used often?”
Neither is universally better. Measure cache hit ratio and workload behavior before changing a stable production policy.
volatile-* policies require TTL discipline
Volatile policies only consider keys with an expiration.
That can create a useful safety boundary when an instance contains both evictable and non-evictable state:
cache keys → TTL set → eligible for eviction important non-expiring keys → no TTL → not selected by volatile policy
But this boundary works only if TTL ownership is consistent.
If developers forget to set expiration on a cache key, it may become effectively non-evictable under a volatile policy and gradually consume memory. If a sensitive key receives a TTL accidentally, it may become eligible for eviction.
Use volatile policies only when the application has strong TTL conventions and monitoring.
volatile-ttl prioritizes keys closest to expiry
volatile-ttl evicts among expiring keys, favoring those with the shortest remaining TTL.
This can make sense when the application already defines useful expiration times and the keys closest to natural expiration are the least costly to remove early.
For example:
key A expires in 20 seconds key B expires in 30 minutes key C expires in 4 hours
Under memory pressure, removing key A first may reduce the difference between natural expiry and forced eviction.
This policy relies heavily on meaningful TTL design. If TTLs are arbitrary or inconsistent, the eviction result will be arbitrary too.
noeviction protects keys but can make writes fail
With noeviction, Redis does not remove keys to make room. Commands that require more memory can fail when the limit is reached.
That is often safer than silent state loss for workloads such as:
- queue metadata;
- coordination state;
- important sessions;
- locks where disappearance changes behavior;
- state that cannot be reconstructed automatically.
The trade-off is operational: the application must handle write failures and the team must react before memory becomes fully exhausted.
noeviction therefore requires:
- memory alerts;
- capacity headroom;
- explicit application error handling;
- a scaling or cleanup procedure;
- TTL or retention rules where appropriate.
Rejecting a write can be better than silently losing existing state, but only when the application understands the failure.
Cache, sessions, queues, and locks should not share one eviction assumption
The biggest architectural risk is combining roles with different loss tolerance in one instance.
| Workload | Eviction tolerance | Safer starting policy |
|---|---|---|
| Rebuildable read cache | High | allkeys-lru or allkeys-lfu |
| Short-lived API cache | High | allkeys-lru, LFU, or suitable volatile policy |
| Sessions | Medium to low | Separate instance or carefully bounded volatile/noeviction design |
| Rate limits | Depends on security/product behavior | Explicit failure policy; avoid accidental eviction |
| Locks | Low | Avoid eviction-based correctness |
| Queue state | Low | Separate workload with persistence/recovery strategy |
One Redis-compatible endpoint can technically support all these patterns, but one memory-loss policy rarely fits all of them.
At Raff, our practical rule is: if evicting one class of keys is normal but evicting another class causes a customer incident, separate the roles before tuning the eviction algorithm.
TTL is a lifecycle policy, not a memory substitute
TTL tells Redis when a key should expire naturally. Eviction handles unplanned memory pressure before that natural expiration.
You need both concepts:
TTL = how long the key is useful maxmemory policy = what happens when memory runs out first
Do not use a very aggressive eviction policy to compensate for missing TTLs.
For cache keys, define:
- expected lifetime;
- invalidation events;
- stale-data tolerance;
- fallback source;
- whether the key can be regenerated cheaply;
- whether the application can tolerate a cache miss storm.
Memory strategy should follow these lifecycle decisions.
maxmemory needs headroom for Redis operations
Setting maxmemory equal to all host RAM is risky because the process and operating system need additional memory beyond stored key data.
Memory can also rise during:
- persistence snapshots;
- AOF rewrite;
- replication buffers;
- client output buffers;
- fragmentation;
- large commands;
- temporary copy-on-write behavior.
Monitor more than the headline memory value:
- used memory;
- RSS/resident memory;
- fragmentation ratio;
- evicted keys;
- expired keys;
- hit/miss ratio;
- rejected writes;
- key count by role or namespace;
- large-key distribution.
A healthy cache is not one that uses 100% of available memory. It is one whose hit rate, eviction rate, latency, and recovery behavior remain within the application's objectives.
Eviction rate should be interpreted with cache hit behavior
Some eviction is normal in a bounded cache. A rising evicted_keys counter is not automatically an incident.
Correlate it with:
- cache hit ratio;
- database fallback load;
- request latency;
- memory growth;
- changes in key size;
- deployment or traffic changes.
For example:
Evictions rise + hit rate stays high + origin database stable = may be normal cache churn
But:
Evictions rise sharply + hit rate collapses + database CPU spikes + latency increases = cache capacity or key lifecycle problem
The application outcome matters more than the eviction counter alone.
Managed Valkey uses the same application-level memory decisions
Raff's managed Redis-compatible path is Managed Valkey. The service reduces host-level operations while keeping cache, queue, session, TTL, and eviction decisions with the application team.
For teams that need exact Redis server configuration, self-hosted Redis on Raff VMs gives direct control over maxmemory, eviction policy, persistence, and host resources.
In either model, the provider cannot decide which application state is safe to discard. That boundary remains with the team that understands the workload.
Redis eviction checklist
- Every key role is classified as disposable or non-disposable.
-
maxmemoryleaves host/runtime headroom. - The selected policy matches allowed data loss.
- Cache keys have deliberate TTLs where appropriate.
- Queue/session/lock state is separated when eviction tolerance differs.
- Eviction, expiration, and rejected-write metrics are monitored.
- Hit ratio is correlated with origin-database load.
- Large keys and memory growth are reviewed.
- Cache warm-up behavior is tested.
- Application behavior under
noevictionwrite failures is understood.
Conclusion
Redis eviction policy is a production reliability decision disguised as a cache setting.
Use all-keys LRU or LFU when every key is safely disposable cache, volatile policies when TTLs deliberately define the evictable set, and noeviction when silent key loss is worse than a write failure. If one instance contains roles with different loss tolerance, separate them before trying to find one perfect eviction rule.