Redis eviction policies determine what Redis does when the dataset reaches the configured maxmemory threshold. Depending on maxmemory-policy, Redis can reject memory-growing writes or evict keys using LRU, LFU, LRM, TTL, or random-selection rules.
For most dedicated caches, allkeys-lru or allkeys-lfu are practical starting points. Use noeviction when silently deleting keys is less acceptable than returning write errors. Use volatile-* policies only when TTLs deliberately identify which keys are safe to evict.
Raff Technologies supports Redis-compatible workloads through Managed Valkey, while teams that need exact Redis configuration can self-host Redis on a Raff VM. In either model, the eviction policy is an application reliability decision: the infrastructure cannot decide which of your keys are safe to lose.
For persistence behavior, see Redis RDB vs AOF. For cache, queue, and session role design, use Redis Cache Strategy for SaaS Apps.
Redis eviction policies: quick decision table
| Policy | Keys eligible for eviction | Selection rule | Typical fit |
|---|---|---|---|
noeviction | None | Reject memory-growing writes | State that must not disappear silently |
allkeys-lru | Any key | Least recently used | General-purpose dedicated cache |
allkeys-lfu | Any key | Least frequently used | Stable hot-set cache |
allkeys-lrm* | Any key | Least recently modified | Read-heavy Redis workloads where stale writes matter more than reads |
allkeys-random | Any key | Random | Uniform/cyclic access patterns |
volatile-lru | TTL keys only | Least recently used | Mixed dataset with deliberate TTL boundary |
volatile-lfu | TTL keys only | Least frequently used | TTL-scoped cache with stable hot set |
volatile-lrm* | TTL keys only | Least recently modified | Redis workloads with TTL-scoped write recency |
volatile-random | TTL keys only | Random | TTL-scoped uniform data |
volatile-ttl | TTL keys only | Shortest remaining TTL | TTL intentionally signals eviction priority |
* Current Redis documentation lists LRM policies starting with Redis 8.6. Valkey's current eviction documentation lists LRU, LFU, random, TTL, and noeviction policies but not LRM. Verify the exact engine and version before depending on LRM behavior.
The most important question is not LRU versus LFU. It is which keys are allowed to disappear when memory pressure arrives.
How maxmemory and eviction work
Redis uses maxmemory to define the dataset memory threshold at which the configured eviction behavior is enforced.
A self-hosted configuration can be set in redis.conf:
maxmemory 4gb maxmemory-policy allkeys-lru
or changed at runtime with CONFIG SET.
The simplified flow is:
Client command adds data → Redis checks memory → memory exceeds maxmemory → eviction policy selects keys, or write is rejected → Redis returns below the dataset limit
A single large command can temporarily push memory noticeably above maxmemory before Redis brings the dataset back under the configured threshold. Treat maxmemory as an eviction threshold, not an exact ceiling for total process RSS.
maxmemory is not the same as total Redis process memory
A common production mistake is setting maxmemory equal to all RAM available to the process or VM.
Redis may need additional memory for:
- replication buffers;
- AOF buffers;
- client buffers;
- allocator overhead and fragmentation;
- persistence operations;
- fork/copy-on-write behavior;
- operating-system processes.
Redis specifically excludes some replication and AOF buffer memory from the value compared against maxmemory. The INFO memory field mem_not_counted_for_evict exposes memory used by those buffers.
For a replicated or persisted deployment, leave headroom instead of treating maxmemory as the machine's physical RAM size.
Useful checks include:
INFO memory INFO stats
Review at least:
used_memory;used_memory_dataset;mem_not_counted_for_evict;- RSS/resident memory;
- fragmentation;
evicted_keys;expired_keys;- keyspace hits and misses;
- rejected commands;
- time spent above the eviction threshold.
allkeys-lru is a strong default for many dedicated caches
LRU means Least Recently Used.
allkeys-lru makes every key eligible for eviction and favors retaining keys accessed recently. It fits applications where recent access is a useful predictor of future demand.
Typical examples include:
- application response caches;
- profile or permission lookup caches;
- dashboard fragments;
- API response caches;
- recently viewed catalog data.
Example:
hot profile → accessed repeatedly → likely retained old dashboard result → not accessed recently → more likely evicted
Redis does not implement mathematically exact LRU. It samples candidate keys and chooses among them, which avoids the memory overhead of maintaining a perfect global ordering.
Redis exposes maxmemory-samples for self-hosted deployments that need to tune the approximation. Increasing the sample count can make eviction closer to exact LRU at the cost of additional CPU work. Do not tune this before measuring whether cache misses are actually a problem.
allkeys-lfu favors a stable hot set
LFU means Least Frequently Used.
Instead of primarily asking which key was accessed recently, LFU tries to preserve keys that are repeatedly useful over time.
That can fit workloads where a relatively small group of keys stays popular while one-off scans or bursts should not displace them.
Typical examples include:
- popular product metadata;
- frequently reused configuration;
- common authorization data;
- API responses with a stable popularity distribution;
- catalog data with a persistent hot set.
The useful distinction is:
LRU → what was used recently? LFU → what is used frequently?
Redis and Valkey both implement LFU approximately rather than maintaining exact access counters for every request. Frequency counters also decay so historically popular keys do not remain permanently protected after traffic patterns change.
Use cache hit rate, eviction rate, origin-database load, and latency to decide whether LFU actually performs better for your workload.
LRU vs LFU vs LRM
The three policies optimize for different signals:
| Policy | Tracks | Better fit when... |
|---|---|---|
| LRU | Recent access | Recent use predicts near-future reuse |
| LFU | Access frequency | A persistent hot set should survive one-off scans |
| LRM | Recent modification | Frequently read but stale/unmodified data should be evicted before actively updated data |
LRM means Least Recently Modified. Current Redis documentation states that LRM is available starting with Redis 8.6 and updates its recency signal on writes rather than reads.
This makes LRM relevant to a read-heavy workload where a key can be read frequently but has not been updated for a long time. In that situation, LRU may keep the key because reads continually refresh its recency, while LRM can still treat it as an old modification candidate.
Do not assume LRM is available across every Redis-compatible engine. Valkey's current documentation does not list LRM among its eviction policies, so check the exact engine/version before putting LRM into configuration or migration runbooks.
volatile-* policies make TTL part of the eviction boundary
Volatile policies only consider keys that have an expiration.
That creates a potential boundary such as:
cache keys → TTL set → eligible for eviction persistent keys → no TTL → not eligible under volatile policy
This can work, but only when TTL ownership is disciplined.
Two failure modes matter:
- A cache key accidentally has no TTL, so it becomes protected from volatile eviction and keeps consuming memory.
- An important key accidentally gets a TTL, so it becomes eligible for eviction.
There is another important behavior: if no keys satisfy the volatile policy's TTL requirement, Redis/Valkey behaves like noeviction and memory-growing writes can fail.
That means a volatile policy is not a guarantee that Redis will always be able to free memory.
Use volatile policies when TTLs are part of the application's explicit data contract, not as a workaround for mixed responsibilities that would be safer on separate instances.
volatile-ttl uses expiry time as an eviction hint
volatile-ttl selects among expiring keys and favors those with the shortest remaining time-to-live.
Example:
key A → expires in 20 seconds key B → expires in 30 minutes key C → expires in 4 hours
Under memory pressure, key A is the strongest eviction candidate because it is already close to natural expiration.
This is useful when the application sets meaningful TTLs that reflect business value or recomputation cost.
It is less useful when TTLs are arbitrary. If expiration times do not represent how disposable a key is, volatile-ttl is using a poor signal.
allkeys-random can fit uniform access patterns
Random eviction is less sophisticated but can be reasonable when all keys have roughly equal reuse probability.
For example, an application that continuously scans or cycles through the entire dataset may not gain much from trying to preserve a recency-based hot set.
Random policies are also simple to reason about operationally:
allkeys-randomcan remove any key;volatile-randomonly removes keys with TTLs.
Do not choose random eviction simply because it is simpler to configure. Use it when the application's access distribution actually makes LRU/LFU signals weak.
noeviction protects existing keys but makes writes fail
With noeviction, Redis does not delete keys to make room.
When the memory threshold is reached, commands that need to add more data can return errors. Read-only operations against existing data can continue.
This may be safer for:
- coordination state;
- important sessions;
- queue metadata;
- locks;
- state where silent deletion is worse than an explicit application error.
But noeviction is not a durability feature. It simply changes the failure mode from hidden key loss to visible write rejection.
Production use therefore needs:
- memory alerts;
- application handling for rejected writes;
- capacity headroom;
- retention or cleanup rules;
- a scale-up or scale-out procedure;
- incident ownership.
A write error is safer than silent state loss only when the application is designed to handle the error.
Cache, sessions, queues, and locks should not share one eviction assumption
The biggest architecture risk is combining workloads that have different loss tolerance.
| Workload | Eviction tolerance | Safer starting approach |
|---|---|---|
| Rebuildable read cache | High | allkeys-lru or allkeys-lfu |
| Short-lived API cache | High | allkeys or carefully designed volatile policy |
| Sessions | Medium to low | Separate instance or explicit failure contract |
| Rate limits | Depends on security/product behavior | Avoid accidental eviction; define fail-open/fail-closed behavior |
| Distributed locks | Low | Do not let eviction define correctness |
| Queue state | Low | Separate role with persistence/recovery plan |
One Redis-compatible endpoint can technically support several of these roles. That does not mean one maxmemory-policy makes sense for all of them.
A practical Raff rule is: if deleting one class of keys is normal but deleting another causes a customer incident, separate those roles before tuning the eviction algorithm.
For workload boundaries, see Redis Cache Strategy for SaaS Apps.
TTL and eviction solve different problems
TTL defines how long a key should exist under normal application behavior.
Eviction defines what happens when memory runs short before that normal lifecycle completes.
TTL = normal key lifetime maxmemory-policy = memory-pressure behavior
A cache key should still have a deliberate lifecycle even when the server is allowed to evict it earlier.
For important cache namespaces, document:
- source of truth;
- expected lifetime;
- invalidation event;
- stale-data tolerance;
- rebuild cost;
- behavior on cache miss;
- effect of mass eviction or cold restart.
Do not use aggressive eviction to compensate for keys that should have expired naturally but never received a TTL.
Monitor eviction with cache outcomes, not one counter
Some eviction is normal for a bounded cache. evicted_keys increasing does not automatically indicate an incident.
Correlate it with:
keyspace_hits;keyspace_misses;- cache hit ratio;
evicted_keys;expired_keys;- origin-database load;
- request latency;
- write rejections;
- memory usage and fragmentation;
- traffic/deployment changes.
A healthy pattern might be:
Evictions rise moderately + hit rate remains high + origin database remains stable + user latency remains stable = normal bounded-cache churn may be acceptable
A problem pattern looks more like:
Evictions spike + hit rate falls + origin database load rises + latency rises = capacity, key lifecycle, or policy mismatch
For noeviction and volatile policies, also monitor rejected commands. Redis exposes command statistics that can show which commands are being stopped after the memory threshold is reached.
Redis and Valkey policy compatibility is similar but not identical
Redis and Valkey share the core eviction model:
maxmemory;noeviction;- LRU;
- LFU;
- random eviction;
- volatile TTL-scoped variants;
volatile-ttl;- approximate sampling algorithms.
But exact policy availability can diverge as the projects evolve. Redis currently documents LRM policies starting with Redis 8.6, while Valkey's current key-eviction documentation does not list LRM.
If you are moving a workload between Redis and Valkey, include the eviction configuration in the compatibility checklist rather than assuming that every maxmemory-policy string is portable.
For the larger migration decision, see Redis vs Valkey: Compatibility, Operations, and Migration.
How this maps to Raff
Raff's managed Redis-compatible path is Managed Valkey. Managed infrastructure reduces host-level operational work, while the application team still owns the meaning of cache keys, TTLs, sessions, queues, and acceptable eviction.
Teams that need direct Redis configuration, exact engine/version control, or host-level access can self-host Redis on a Raff VM.
The decision path is:
Want less host/database operations → evaluate Managed Valkey Need exact Redis maxmemory-policy or host controls → self-host Redis on a VM
Use current live product pages for service scope rather than treating static article copy as the source of truth for plan limits or managed-database capabilities.
Redis eviction production checklist
- Every key role is classified as disposable or non-disposable.
-
maxmemoryleaves runtime and operating-system headroom. - Replication/AOF buffer memory is considered where applicable.
- The selected policy matches the workload's allowed data loss.
- TTL keys are deliberate if a
volatile-*policy is used. - The team knows volatile policies can fall back to write rejection when no eligible TTL keys exist.
- LRU, LFU, or LRM is chosen from an actual access/update pattern.
- Exact Redis/Valkey policy support is verified for the deployed version.
- Cache hit/miss and eviction metrics are monitored together.
- Rejected writes are monitored for
noevictionor volatile-policy exhaustion. - Queue/session/lock state is separated when loss tolerance differs.
- Cache warm-up and mass-eviction behavior are understood.
Conclusion
Redis eviction policy determines which failure mode appears when the dataset reaches its memory boundary.
Use allkeys-lru when recent use is the best signal for future reuse, allkeys-lfu when a stable hot set matters, and Redis 8.6+ LRM when recent modification—not recent reading—is the useful signal and your exact engine supports it. Use volatile policies only when TTLs deliberately define the evictable set, and use noeviction when rejecting writes is safer than silently deleting existing state.
The best policy is the one that preserves the right data and produces a failure mode your application is prepared to handle.