Skip to content
Navigation

Type at least two characters. Search covers page titles, headings, tags and database names.

↑ ↓ to navigateEnter to openEsc to close0 pages
Redis and Valkeybeginner

Redis Key Expiration

How TTLs are enforced, why expired keys can persist in memory, and the operations that silently remove an expiry.

2 min readBeginnerUpdated Edit this page

A TTL marks a key for automatic deletion. Expiry is how a cache stays bounded without an eviction policy having to do the work.

SET shop:session:abc "…" EX 3600        # set with expiry, atomically
EXPIRE shop:cart:9f3a 1800              # add expiry to an existing key
TTL shop:cart:9f3a                      # seconds remaining, -1 no TTL, -2 no key
PERSIST shop:cart:9f3a                  # remove the expiry

How expiry actually happens

Two mechanisms, and neither is instantaneous:

  1. Lazy expiration. When a key is accessed, Redis checks whether it has expired and deletes it then.
  2. Active expiration. A background cycle samples keys with TTLs and removes expired ones, repeating while it finds a high proportion expired.

The consequence: an expired key that nobody accesses continues to occupy memory until the active cycle happens to sample it. Memory does not drop the instant a large batch of keys expires. On replicas, expired keys are not deleted independently — the primary sends an explicit DEL, so a replica may briefly hold keys that are logically gone.

Operations that remove the TTL

Note that TTLs apply to the whole key. There is no per-field expiry in a hash in core Redis — a common wrong assumption when modelling objects as hashes.

Choosing TTLs

  • Always set one on cache entries. A cache without expiry is a memory leak with good latency.
  • Add jitter. Thousands of keys created together with an identical TTL expire together, causing a synchronised miss storm against the origin. See Cache Stampede.
ttl = base_ttl + random.randint(0, base_ttl // 10)
  • Match the TTL to tolerable staleness, not to convenience. If a stale value for ten minutes is acceptable, ten minutes is the answer.

Monitoring

INFO stats        # expired_keys, evicted_keys
INFO keyspace     # keys and keys-with-expiry per database

db0:keys=1450000,expires=1200000 tells you 250,000 keys have no TTL. If that number grows, keys are being created without expiry or having it cleared — worth investigating before memory does it for you.

Keyspace notifications can publish expiry events, which is occasionally useful:

notify-keyspace-events Ex