Module F-5·20 min read

How Redis expires keys via lazy and active expiry, the seven eviction policies (allkeys-lru, volatile-ttl, noeviction and more), maxmemory configuration, and how to monitor evictions with INFO stats.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

F-5 — TTL, Expiry, and Eviction

Who this module is for: You have set expiry on keys using EX but never thought about what happens when Redis runs out of memory, how it decides which keys to delete, or why your cached data sometimes disappears before the TTL expires. This module covers the full lifecycle of a key from creation to deletion — including the seven eviction policies, lazy vs active expiry, and how to design your keyspace so you never get surprised by silent data loss.


The Key Lifecycle

Every Redis key passes through the same lifecycle:

Created → [Optional TTL set] → Accessed / Modified → Expired or Evicted → Deleted

Understanding each transition is the difference between a cache that behaves predictably and one that silently drops data at 3 AM under load.


Setting Expiry

You already know the inline EX option on SET. Redis gives you several ways to set expiry — on creation or after the fact.

On Creation (SET options)

text

After Creation (standalone commands)

text

As of Redis 7.0, EXPIRE and PEXPIRE accept option flags:

text

These are useful for conditional TTL management — for example, extending a session TTL on activity (GT), or ensuring a key's TTL only decreases (LT) for rate-limit windows.

Querying TTL

text

-1 and -2 are easy to confuse. -1 means the key exists but has no expiry (persistent). -2 means the key does not exist at all — either it was never set or it already expired.

Removing TTL

PERSIST key → remove the TTL, making the key persistent again

This is useful when you want to "promote" a cached object to permanent storage without deleting and re-creating it.

text

How Expiry Works Internally

Redis does not run a background thread that continuously checks every key for expiry. That would be prohibitively expensive with millions of keys. Instead, Redis uses two complementary mechanisms:

1. Lazy Expiry

When a client accesses a key — via GET, SET, EXISTS, or any other command — Redis checks whether the key has an expired TTL before returning the value. If it has expired, Redis deletes it on the spot and returns (nil).

This is "lazy" because the deletion only happens when the key is accessed. A key that expires at 14:00 but is never accessed again after 13:59 will still occupy memory at 15:00.

2. Active Expiry (Periodic Sampling)

To handle keys that expire but are never accessed again, Redis runs an active expiry cycle on a timer (by default 10 times per second, controlled by hz config — default 10). Each cycle:

  1. Takes a random sample of 20 keys from the set of all keys with a TTL
  2. Deletes any that have expired
  3. If more than 25% of the sampled keys were expired, repeats the cycle immediately (keeps going until < 25% are expired)

This adaptive approach means Redis spends more time on expiry cleanup when there are many expired keys, and less time when the keyspace is healthy. The trade-off: a key that expires may remain in memory for up to 100ms after expiration (one hz cycle) if it is never accessed.

In practice: Your application should always handle (nil) from GET even if a key should still be live — clock skew, replication lag, and the expiry timing mean you cannot rely on exact expiry moments.


Eviction: When Redis Runs Out of Memory

Expiry handles keys that have a TTL. What about keys with no TTL when Redis hits its memory limit?

When Redis reaches its configured maxmemory limit, it must decide what to do with new write commands. The behavior is controlled by maxmemory-policy.

Setting maxmemory

In redis.conf or at runtime:

text

At runtime:

text

If maxmemory is 0 (the default), Redis uses all available RAM on the machine. Always set maxmemory in production. Letting Redis exhaust system RAM will cause the OS to start swapping (millisecond latencies become second latencies) or OOM-kill the Redis process.

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.