...

Redis Eviction Policies for Hosting Servers: The Right Strategy

On hosting servers, Redis Eviction determines which keys are evicted when memory is scarce and which remain in the cache, ensuring that requests are delivered reliably and quickly. I'll show you specific strategies for choosing the right policy, configure and ensures this through monitoring.

Key points

Before I get into the details, I'll briefly summarize the most important decisions so you can Policy can quickly determine. The following points are intended for hosting administrators, DevOps professionals, and website operators focused on performance. I take into account typical workloads ranging from pure cache to mixed datasets with TTL and persistent keys. This helps you maintain the right balance between cache ratio, data security, and predictability. With these key points in mind, you can make a clear Choosing a server.

  • Allkeys-LFU: For broad cache workloads with highly unevenly distributed accesses.
  • Allkeys-LRU: For fresh content and predictable behavior.
  • Volatile-LRU/LFU: Deletes only TTL keys; protects persistent data.
  • No Eviction: For critical data; typos instead of lost keys.
  • Monitoring: Keep a close eye on the hit rate, memory, and evictions at all times.

What exactly does Redis eviction mean?

Redis eviction refers to the removal of keys as soon as the set maxmemory has been reached and Redis needs to free up space so that new data can be written. I control this behavior using the setting maxmemory policy, which includes options such as allkeys-lru, allkeys-lfu, allkeys-random or the volatile-*-offers several variants; each option prioritizes different keys for removal. LRU protects recently used keys, LFU favors frequently used data, Random selects keys at random via sampling, and volatile policies consider only keys with a time-to-live (TTL). Important: Redis makes its deletion decisions efficiently through sampling, which keeps latency low and ensures the system operates reliably controls. Eviction only kicks in when memory becomes scarce; until then, Redis behaves like a normal in-memory data store with Cache-Advantages.

Choosing the Right Policy for Hosting Servers

The best policy depends on determining which data must remain in memory and which the system is allowed to recalculate. If Redis is used exclusively as a cache, an "allkeys" strategy is appropriate because, if in doubt, each entry can be regenerated from the original source; in that case, allkeys-lfu in the case of unequal access and allkeys-lru for more recent content. If the instance contains a mix of data, I prefer volatile-lru or volatile-lfu, so that only TTL keys are deleted and persistent data remains unaffected. If the data is critical, I rely on no eviction, but I accept that write commands will fail when memory is fully utilized, and the application must respond correctly. This simple decision-making logic makes operation predictable, keeps the risk of errors low, and gives me a clear Guard rail.

Practical Guide: Cache-Only vs. Mixed Workloads

For pure cache workloads, I aim for a high hit rate and accept that evictions pose little risk because data is quickly reloaded from the primary source. In such environments, allkeys-lfu is often the best compromise, since frequently used objects remain in memory for a long time, while less frequently used data is evicted. If you're aiming for up-to-date data, choose allkeys-lru, to prioritize recently used entries and keep recent page fragments in the cache. For mixed data sets, I use TTL on all cache keys and combine that with volatile-lru or volatile-lfu, so that only clearly „temporary“ data is deleted. A well-configured storage setting supports this choice; I provide additional tips in my guide Optimize Storage Configuration, which examines specific MaxMemory reserves and metrics.

LRU vs. LFU: When to Use Which Method

LRU (Least Recently Used) prioritizes the recency of the last use and ensures that recently accessed content is retained. LFU (Least Frequently Used) counts the frequency of access and thus protects „evergreen“ content, even if it hasn’t been accessed in the last few minutes; this pays off noticeably for highly irregular access patterns. If usage patterns change rapidly—for example, with news or campaigns—it has an effect allkeys-lru more intuitive, as it places greater emphasis on current activity. It works well for stable, recurring patterns such as menus, home page widgets, or login-related data allkeys-lfu, because the content remains available at all times. To avoid misjudgments, I regularly check the hit rate, eviction rate, and response times, because these figures reflect the actual Use reliable.

Fine-Tuning for LRU/LFU

To ensure that the LRU/LFU operate accurately, I adjust three set screws: maxmemory-samples, lfu-log-factor and lfu-decay-time. Higher maxmemory-samples-Values (e.g., 10–15 instead of the default) improve the sample quality during evictions and thus increase the hit rate for the „correct“ keys, but they consume CPU resources. lfu-log-factor controls how quickly the LFU counter increases: Low values react quickly (good for short-lived trends), while high values smooth out the curve (better for long-lasting „heavy hitters“). With lfu-decay-time (in minutes) I define how quickly old popularity „expires“; higher values are suitable for daily patterns, while lower values are better for rapidly changing content. I always change only one parameter per iteration, monitor the hit rate, and keep an eye on latency to avoid unnecessarily tying up the CPU in sampling.

TTL Strategies with volatile-*

TTL-based policies such as volatile-lru and volatile-lfu Limit deletions to keys with an expiration time and leave „persistent“ keys untouched. This is suitable for setups where Redis stores cache data and long-lived data together, such as session-like information alongside query caches. If I consistently set TTLs on all cache keys, I can ensure that evictions occur only where I intend them to. Important: If the database contains no TTL keys, volatile policies behave like no eviction, that is, without clearing the cache and with potential write errors when the cache is full. That's why I regularly check whether all cache objects have a reasonable lifetime and whether the time intervals until the actual Actuality match the content.

As an additional option, I use this for content with a clearly defined time frame volatile-ttl, which causes keys with the shortest remaining lifetime to be removed first. This is useful when all cache objects are going to be refreshed soon anyway, and I want to use the „natural“ expiration date as the priority. For testing or staging, I occasionally set volatile-random to minimize CPU load; in production, I avoid random variants because they are less predictable.

No Eviction for Critical Data

At no eviction Redis does not delete keys; read operations remain possible, while write commands may fail once the memory limit is reached. This protects critical data from unintended deletion but requires the application to handle error messages robustly and, if necessary, apply backpressure. I use `noeviction` in cases where cache loss would be more costly than temporary write errors, such as for security-related settings or highly sensitive session information. It remains important to plan memory usage conservatively with a reserve, so that spikes do not immediately result in errors and the Application continues to respond. In addition, I actively issue warnings through monitoring before the threshold is reached, in order to take timely action to counteract.

Persistence, Replication, and Storage Buffers

Eviction decisions should always be made in the context of persistence (RDB/AOF) and replication. RDB snapshots and AOF rewrites use copy-on-write; during this process, the RSS memory temporarily increases. I therefore plan for a buffer of 25–50% above the observed peak to ensure that a rewrite does not unintentionally trigger evictions. The magnitude depends on the write rate and object size; the more objects that change during the rewrite, the greater the requirement.

When replicating, I make sure to follow the repl-backlog-size as well as the output buffers for replicas. Especially important: I often use replicas replica-ignore-maxmemory yes (formerly slave-ignore-maxmemory), so that the replica server isn't automatically evicted during peak loads while it is following the primary server. For read replicas that act as caches, however, I can deliberately enable an eviction policy if I need to strictly limit storage. For critical data, I like to pair replicas no eviction with sufficient margin to avoid data discrepancies.

Configuration in redis.conf and at runtime

I work in a reproducible manner using clear settings and save them permanently:

# Example: Cache-only, uneven access
maxmemory 4gb
maxmemory-policy allkeys-lfu
maxmemory-samples 10
lfu-log-factor 10
lfu-decay-time 1

# Optional Background Evictions (see Lazyfree)
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes

At runtime, I test changes using CONFIG SET and write them down using CONFIG REWRITE permanently in the configuration file. For mixed workloads, I document TTL rules in the code and keep the Redis instances separated by purpose (e.g., separate cache vs. sessions) so that each instance can run a focused policy.

Lazyfree: Evictions Without Latency Spikes

Large keys or bulk deletions quickly cause synchronous latency spikes. With Lazyfree (lazyfree lazy eviction, lazyfree-lazy-expire, lazyfree-lazy-server-del) I move the release of large objects to background threads; commands such as UNLINK instead of DEL They use that, too. The result: more consistent response times under the same workloads. I keep an eye on memory and CPU usage, because background releases can cause additional overhead in the short term.

Monitoring and Metrics: Hit Rate, Memory, Evictions

A well-balanced setup stands or falls on visibility: I measure the Hit rate, the eviction rate, latency, and memory usage over time. If the eviction rate rises while the hit rate falls, these figures indicate insufficient memory, incorrect TTLs, or an inappropriate policy. During peak times, I also evaluate the error rates of write commands to immediately identify noeviction risks. The Redis-internal samples for LRU/LFU can be accessed via maxmemory-samples Adjust; higher values lead to better decisions but consume some CPU resources. I increase this value moderately, monitor the effect on response times, and thus find the best Setting for the workload.

Sample Configurations for Hosting Servers

For recurring hosting scenarios, a small matrix has proven useful; I use it as a starting point and then refine it based on measurements. I always plan for a reserve when maxmemory, so that load spikes are buffered and evictions occur in an orderly manner. To do this, I select the policy based on the workload according to the table below and clearly document TTL rules in the application. This approach prevents misunderstandings between Dev and Ops and ensures reproducible behavior in day-to-day operations. With this kind of overview, I keep my Decisions transparent and makes it easier to customize.

Workload Recommended Policy Advantage Risk Note
Pure cache, uneven access patterns allkeys-lfu Frequently used items remain Rare keys drop more quickly Check the hit rate, maxmemory-samples fine-tune
Pure cache, current content allkeys-lru Recently used keys remain Long-time favorites tend to fall Often more suitable for news/campaigns
Mixed Data with TTL volatile-lru/lfu Permanent keys protected No TTL, no deletion Consistently apply and document TTL
Critical Data Storage no eviction No lost keys Typos When RAM Is Full Ensure Proper Error Handling in the App
Test/Staging allkeys-random Very low CPU overhead Unpredictable Evictions Do not use in production caches

Shared vs. Dedicated Redis in Hosting

In shared environments, you often have to deal with fluctuating load profiles and unclear TTL rules from other projects, which can make evictions seem unpredictable. I prefer to use volatile-lru or volatile-lfu and set short, clear TTLs on all cache keys so that only explicitly ephemeral data is evicted. In dedicated high-performance caches, this provides allkeys-lfu often better hit rates and more stable response times, because „heavy hitters“ reliably remain in RAM. If you’re still unsure about which option to choose, check out my guide to Shared vs. dedicated, where I compare the effects on performance, isolation, and costs. With this clarity, I reduce the risk of side effects and maintain the Latency under control.

Redis does not enforce quotas per client natively. If I need strict storage budgets, I start separate instances or cluster shards for each project and define a separate one for each instance maxmemory along with the appropriate policy. This prevents individual tenants from dominating the shared memory and unintentionally triggering evictions for others.

WordPress and WooCommerce: Configuring the Object Cache Correctly

In WordPress setups, query results, menus, login information, and transient data often end up in the Redis object cache; these keys are ideal for TTL-based rules. For dynamic pages, I set short TTLs for transient content so that volatile-lfu or volatile-lru Create space in a targeted manner. If the page relies heavily on recurring elements, it’s important to allkeys-lfu, because „long-running processes“ remain in memory and the cache ratio stays high. I explain typical errors in the object cache here: Configuration error in the object cache, where I discuss TTL, namespaces, and key size. These adjustments help me prevent unnecessary misses and keep the site running smoothly during peak traffic times fast.

Practical Guidelines: For highly volatile fragments (e.g., personalized widgets, shopping cart snippets), I choose TTLs in the range of seconds to a few minutes. For menu structures, categories, or homepage widgets, longer TTLs make sense, provided that a cache invalidator reliably triggers when changes occur. WooCommerce catalogs often benefit from prewarm jobs (Cron) that specifically populate top product lists after cache flushes. Also, make sure that plugins do not write oversized objects to the object cache; if necessary, break them down into smaller units (multiple smaller keys instead of one gigantic blob) and streamline data formats.

Operating System and Container Tuning

OS and container defaults indirectly influence evictions through memory availability and RSS behavior. I set vm.overcommit_memory=1, disable Transparent Huge Pages (THP) and avoid swapping in production caches to prevent the OOM killer and reduce RSS bloat. In containers, I configure the maxmemory below the cgroup limit and leave some headroom for RDB/AOF spikes, replication buffers, and fragmentation. This prevents the process from being forcefully terminated due to brief spikes, even though Redis-side eviction might still be effective. In my monitoring, I keep an eye on, in addition to used_memory also used_memory_rss and the ratio (mem_fragmentation_ratio), in order to respond effectively to operating system effects.

Active Defragmentation and Memory Reserves

Redis can fragment memory internally, which reduces available RAM and triggers evictions earlier than expected; with defragmentation enabled, I mitigate this behavior. I therefore plan for a buffer above the expected peak usage and regularly check the Fragmentation as well as actual usage. Limits that are too tight lower the hit rate, while limits that are too generous carry the risk of delayed errors if noeviction is enabled. Take small steps when adjusting maxmemory help me keep the effects measurable and avoid overcompensating blindly. This way, storage planning remains realistic and the Performance constant.

With activedefrag yes and finer boundaries (cycle-min/max) I smooth out memory spikes without putting too much strain on throughput. I prefer to run defragmentation outside of peak load periods and then assess whether evictions occur less frequently or in a more orderly manner.

Targeted Streamlining of Big Keys and Data Structures

Disproportionately large keys create holes in the cache and trigger harsh evictions. I look for such outliers using redis-cli --bigkeys or MEMORY USAGE per key and use MEMORY STATS/MEMORY DOCTOR as an initial diagnosis. Common solutions: Split large JSON blobs, use hashes with compact encodings (set appropriate Listpack/Ziplist thresholds), reconsider the granularity of sets and sorted sets, and actively trim old members. For streams, I keep an eye on both the input and consumer sides: With XTRIM I limit the length and avoid PELs (Pending Entries) that grow indefinitely by reliably and diligently processing consumers or cleaning up inactive groups.

Specific Tuning Steps for Everyday Life

I start with a clear policy based on workload, set realistic TTLs, and monitor the hit and eviction rates throughout the day. Then I adjust maxmemory in small steps and adjust maxmemory-samples to make better LRU/LFU decisions. If the hit rate drops despite increasing memory, the problem often lies in TTLs that are too short, objects that are too large, or incorrect key granularity; in that case, I optimize the Keys and reduce unnecessary data. With WordPress, I check the size and number of objects in the cache, as well as the behavior of plugins that write too aggressively to the cache. With each iteration, the eviction rate decreases, response times become more consistent, and the cache handles the Load reliable.

Runbook: When Evictions Get Out of Hand

  • Validate Alarms: Hit/Miss Rate, Evictions, Error Messages (OOM command not allowed), Check latencies.
  • Immediate action: Temporary, if possible maxmemory Increase it slightly to improve stability; alternatively, limit traffic (rate limit/backpressure).
  • Adjust policy: If using "Cache-only," set to allkeys-lru Switch to make space more aggressively; enable Lazyfree to avoid latency spikes.
  • Targeted cleanup: Unimportant namespaces via SCAN + UNLINK Delete; check TTLs and increase timers that are too short if reloading overloads the primary source.
  • Identifying large-scale consumers: --bigkeys, MEMORY USAGE, large streams/sorted sets; mark hotkeys for prewarm.
  • Be aware of persistence: Is an RDB/AOF rewrite in progress? Ensure there is enough headroom or reschedule the window.
  • Post-stabilization: Fine-tuning of maxmemory-samples, LFU parameters, defragmentation; document the learning effect.
  • Long-term prevention: Update capacity planning, implement separate instances for different policies, and refine metric alerts.

Concluding overview

In practice, for simple caches, I usually rely on allkeys-lfu, for fresh content on allkeys-lru, using `volatile-policies` for mixed data and `noeviction` for sensitive data. Clear TTLs, sufficient memory reserves, and visible monitoring remain crucial to ensure that evictions run predictably and without surprises. With this structure, I avoid data loss, keep the hit rate high, and respond calmly to traffic spikes. The table above helps get started; the metrics then guide the fine-tuning. This way, every hosting environment finds a simple, resilient Strategy for Redis eviction and delivers pages quickly and consistently from.

Current articles