Redis Expiry and TTL

Every key in Redis can carry an expiry — a countdown timer that deletes the key automatically when time runs out. This feature keeps Redis from filling up with stale data and removes the need to write cleanup jobs. You set the expiry when you create a key, or attach it afterward.

The Parking Ticket Analogy

A parking ticket is valid for two hours. When the time expires, the ticket becomes invalid and the parking space opens up. You do not need anyone to manually cancel the ticket — time does that work. A Redis key with an expiry works the same way.

Key created at 10:00 AM with a 2-hour expiry:

10:00 AM  │ SET otp:user99 "847261" EX 7200
          │
          │  ┌──────────────────────────┐
          │  │  Key: otp:user99         │
          │  │  Value: "847261"         │
          │  │  Expires at: 12:00 PM    │
          │  └──────────────────────────┘
          │
11:00 AM  │ GET otp:user99 → "847261"  ✓ (still valid)
          │
12:01 PM  │ GET otp:user99 → (nil)     ✗ (expired, auto-deleted)

Setting Expiry at Creation Time

EX sets expiry in seconds:
  SET session:abc123 "user:1001" EX 1800
  (expires in 30 minutes = 1800 seconds)

PX sets expiry in milliseconds:
  SET rate:limit:ip1 "1" PX 60000
  (expires in 60 seconds = 60000 milliseconds)

EXAT sets expiry as a Unix timestamp (specific point in time):
  SET promo:flash "DEAL50" EXAT 1711929600
  (expires at that exact Unix timestamp)

Attaching Expiry to an Existing Key

127.0.0.1:6379> SET token "xyz789"
OK
127.0.0.1:6379> EXPIRE token 300
(integer) 1    ← expiry set (300 seconds = 5 minutes)

To set expiry with a specific Unix timestamp on an existing key:
127.0.0.1:6379> EXPIREAT token 1711929600
(integer) 1

Checking Remaining Lifetime with TTL

TTL returns time remaining in seconds.
PTTL returns time remaining in milliseconds.

127.0.0.1:6379> TTL token
(integer) 287    ← 287 seconds left

127.0.0.1:6379> TTL no_expiry_key
(integer) -1     ← -1 means no expiry set (lives forever)

127.0.0.1:6379> TTL deleted_key
(integer) -2     ← -2 means key does not exist

Removing Expiry Without Deleting the Key

127.0.0.1:6379> PERSIST token
(integer) 1    ← expiry removed; key now lives indefinitely

127.0.0.1:6379> TTL token
(integer) -1   ← confirms no expiry

How Redis Deletes Expired Keys (Under the Hood)

Redis uses two strategies to clean up expired keys. Understanding both explains why a key disappears exactly when you access it, even if Redis has not cleaned it yet.

Strategy 1: Lazy Expiry
  Redis does NOT scan for expired keys constantly.
  When you GET a key, Redis first checks its expiry.
  If expired → Redis deletes it right then and returns (nil).

  GET expired_key
     │
     ▼
  Redis checks: is this key expired?
     │
  YES → delete now → return (nil)
   NO → return value

Strategy 2: Active Expiry (Background Sweep)
  Every 100 milliseconds, Redis samples ~20 random keys
  that have an expiry set, deletes the expired ones,
  and repeats if more than 25% were expired.

  This prevents expired keys from sitting in memory
  for too long even if nobody reads them.

Practical Patterns

One-Time Password (OTP)

User requests OTP. Server generates "481923".
SET otp:user:1001 "481923" EX 300   ← valid for 5 minutes

User submits OTP:
  GET otp:user:1001
  → "481923" if still valid
  → (nil) if expired (OTP rejected automatically)

After correct submission, delete it immediately:
  DEL otp:user:1001

Rate Limiting (Requests Per Minute)

Each IP gets a counter that resets every 60 seconds:
  INCR rate:192.168.1.5
  EXPIRE rate:192.168.1.5 60   ← reset after 1 minute

On each request:
  count = INCR rate:192.168.1.5
  if count == 1: EXPIRE rate:192.168.1.5 60
  if count > 100: block the request

After 60 seconds, Redis deletes the key.
Next request starts a fresh counter from 1.

Sliding Cache with Refresh

Cache a user's dashboard data for 10 minutes.
Each time the user opens the dashboard, refresh the timer.

  SET dashboard:user:55 "..." EX 600

  Each visit:
    GET dashboard:user:55
    if found: EXPIRE dashboard:user:55 600   ← slide the window
    if not found: rebuild + SET with EX 600

Key Points

  • Use EX (seconds) or PX (milliseconds) with SET to create a key that auto-deletes.
  • EXPIRE attaches a timer to an already-existing key.
  • TTL shows remaining seconds; -1 means no expiry; -2 means the key is gone.
  • PERSIST removes the expiry, making the key permanent again.
  • Redis uses lazy deletion (on access) and periodic sampling to clean expired keys efficiently.

Leave a Comment