Skip to content

Step 1 of 3 · Reading · ~3 min

Key Expiry

Key Expiry

EXPIRE & TTL — Setting Timeouts

Every key-value store eventually needs a way to say "forget this after a while" — session tokens, cache entries, rate-limit windows. This lesson introduces the second core data structure of your Redis clone: an expiry table sitting alongside the value store.

Storing expiry as an absolute deadline, not a countdown

The natural-seeming approach — "store the TTL in seconds, count it down" — is wrong, because you'd need a background timer ticking every key down constantly. Real Redis (and your implementation) instead stores an absolute expiration timestamp: "this key dies at wall-clock time T." Checking whether a key is expired then becomes a single comparison, now >= expire_at, with no ongoing bookkeeping required.

python

TTL

TTL reports how much time is left, computed on demand from that same absolute timestamp:

python

The three possible return values are a small but important contract: -2 means "key doesn't exist at all," -1 means "key exists but has no expiry (persists forever)," and any non-negative number is seconds remaining. Client code branches on these three cases constantly, so get the boundary conditions exactly right.

PERSIST

PERSIST removes a key's expiry, making it permanent again, without touching its value:

python

It returns 1 only if there was a TTL to remove — calling PERSIST on a key that never had one returns 0, same as calling it on a nonexistent key.

A simulated clock for deterministic tests

Real time is awkward to test against — you don't want your test suite to sleep() for real seconds. This course's harness instead gives you a WAIT <ms> pseudo-command that advances a virtual clock you control:

python

Route all your expiry math through this now() function — never call the real system clock directly — so that WAIT 5000 behaves identically to five real seconds passing, instantly and deterministically.

Edge cases

  • EXPIRE on a nonexistent key must return 0 and must not create a phantom expiry entry.
  • Setting EXPIRE key 0 or a negative value should generally delete the key immediately (real Redis does this) — worth deciding deliberately rather than leaving as undefined behavior.
  • This lesson only sets up the bookkeeping; actually enforcing expiry on GET/EXISTS/DBSIZE is the subject of the Passive Expiry lesson later in this chapter.
Up nextSET with EX — Atomic Set+ExpireKey Expiry

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…