Redis Tutorial 0/42 lessons ~6 min read Lesson 16

    Expiration & TTL

    TTL (time-to-live) is non-negotiable for cache keys — without EX/PX every SET lives forever until manual DELETE or OOM.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    TTL (time-to-live) is non-negotiable for cache keys — without EX/PX every SET lives forever until manual DELETE or OOM. Redis expires keys passively on access and actively via sampling (~10 keys/second per DB plus faster cycle when memory pressure hits).

    Mass simultaneous expiry causes cache stampede — thousands of requests hit DB when hot keys expire together. Jitter TTL and single-flight refresh prevent avalanches.

    volatile-* eviction policies only remove keys with TTL set — understand the difference from allkeys-*.

    Understanding the topic

    Key concepts

    • EX seconds / PX milliseconds on SET — set with expiry.
    • EXPIRE key seconds — add TTL to existing key.
    • TTL key — remaining seconds; -1 no expiry; -2 missing.
    • PERSIST — remove TTL.
    • Passive expire on read; active random sampling.
    • volatile-lru evicts expirable keys when maxmemory hit.
    text
    flowchart LR
    SET -->|EX| KeyTTL
    Access -->|passive| Delete
    Sample -->|active| Evict

    Step-by-step explanation

    1. Expiry stored in key metadata dict.
    2. On access, Redis checks expiry and deletes if past.
    3. Active cycle samples random keys with TTL.
    4. Expired keys deleted or evicted per policy.
    5. EXPIREAT/PEXPIREAT use absolute Unix timestamps.

    Syntax reference

    Common commands

    • Always EX on cache writes.
    • TTL -2 means key gone — treat as cache miss.
    • Add random jitter in app: baseTtl + random(0, 60).
    bash
    SET session:abc data EX 3600
    TTL session:abc
    EXPIRE cache:product:1 1800
    SET cache:flag 1 EX 300 NX

    Informative example

    Cache write with jittered TTL to reduce stampede:

    bash
    # Shell illustrates jitter concept
    BASE=3600
    JITTER=$(( RANDOM % 300 ))
    redis-cli SET "product:42" "$JSON" EX $((BASE + JITTER))

    In Java: Duration.ofSeconds(3600 + ThreadLocalRandom.current().nextInt(300)). Spring @Cacheable supports custom TTL per cache name.

    Real-world use

    Real-world use cases

    • Session timeout — EXPIRE aligned with JWT.
    • API cache — 5–60 min TTL by volatility.
    • Rate limit windows — EXPIRE on counter key.
    • OTP codes — EX 300 one-time.
    • Distributed lock — SET NX EX auto-release.

    Best practices

    • TTL on every cache key — no exceptions.
    • Jitter TTL on hot keys.
    • Refresh TTL on session activity (sliding window).
    • Monitor expired_keys_per_sec in INFO stats.
    • Use volatile-lru when most keys have TTL.
    • Plan stampede protection (sync=true, mutex).

    Common mistakes

    • Forever keys — memory leak.
    • Identical TTL on millions of keys — thundering herd.
    • Assuming EXPIRE extends on read without EXPIRE call.
    • volatile-lru with keys missing TTL — they never evict.

    Advanced interview questions

    Q1BeginnerTTL return values?
    -2 key missing; -1 exists no TTL; positive seconds remaining.
    Q2BeginnerPassive vs active expiry?
    Passive on access; active random sampling deletes expired keys.
    Q3IntermediateWhat is cache stampede?
    Many requests miss cache simultaneously after expiry and hammer DB.
    Q4IntermediatePrevent stampede?
    Jitter TTL, mutex/single-flight, stale-while-revalidate, early async refresh.
    Q5Advancedvolatile-lru vs allkeys-lru?
    volatile only evicts keys with TTL; allkeys evicts any key at maxmemory.

    Summary

    TTL prevents unbounded memory growth.

    Ready to mark this lesson complete?Track your journey across the entire course.