Skip to content

Expiration & TTL

Redis is often used as a cache or a session store. In both cases you want keys to disappear automatically after some time — you should not have to write cleanup jobs. Redis handles this natively through key expiration.

You can attach a TTL (time-to-live) when you create a key, or add one to an existing key:

CommandDescription
SET key val EX secsCreate + expire in seconds
SET key val PX msCreate + expire in milliseconds
EXPIRE key secsSet/update expiry in seconds on existing key
PEXPIRE key msSet/update expiry in milliseconds
EXPIREAT key unix-secsExpire at an absolute Unix timestamp (seconds)
PEXPIREAT key unix-msExpire at an absolute Unix timestamp (milliseconds)
127.0.0.1:6379> SET session:abc "user:42" EX 300
OK
127.0.0.1:6379> TTL session:abc
(integer) 299
127.0.0.1:6379> SET cache:home "<html>...</html>"
OK
127.0.0.1:6379> EXPIRE cache:home 60
(integer) 1
127.0.0.1:6379> TTL cache:home
(integer) 59
SET session:abc "user:42" EX 300
TTL session:abc
SET cache:home "<html>...</html>"
EXPIRE cache:home 60
TTL cache:home

TTL returns seconds; PTTL returns milliseconds. Both have two special return values:

  • -1 — the key exists but has no expiry (it is persistent)
  • -2 — the key does not exist (or has already expired)
127.0.0.1:6379> SET persistent "I live forever"
OK
127.0.0.1:6379> TTL persistent
(integer) -1
127.0.0.1:6379> TTL nonexistent:key
(integer) -2
127.0.0.1:6379> SET brief "gone soon" PX 5000
OK
127.0.0.1:6379> PTTL brief
(integer) 4987
SET persistent "I live forever"
TTL persistent
TTL nonexistent:key
SET brief "gone soon" PX 5000
PTTL brief

If you want to cancel a key’s expiry and make it persistent again, use PERSIST:

127.0.0.1:6379> SET promo "SALE10" EX 3600
OK
127.0.0.1:6379> TTL promo
(integer) 3599
127.0.0.1:6379> PERSIST promo
(integer) 1
127.0.0.1:6379> TTL promo
(integer) -1
SET promo "SALE10" EX 3600
TTL promo
PERSIST promo
TTL promo

Redis uses two complementary strategies — you do not need to do anything, but understanding them helps you reason about memory:

Lazy expiry — when you access a key (GET, EXISTS, etc.), Redis checks its expiry first. If it has expired, Redis deletes it right then and returns (nil) as if it never existed.

Active expiry — Redis runs a background cycle (by default ~10 times per second) that randomly samples keys with TTLs and deletes the ones that have expired. This prevents the keyspace from filling up with keys that are never accessed.

Together these strategies keep memory usage bounded without blocking your application.

What does TTL return for a key that exists but has no expiration set?
Which command cancels an expiration and makes a key persistent?
What does PEXPIRE set compared to EXPIRE?
What does lazy expiry mean in Redis?