Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

Redis Expire: The TTL, the EXPIRE Command, the Key Expiration, and the One Mistake That Fills the Memory

Sean

Platform Writer

Jun 23, 2026
6 min read

Redis expire is the TTL (Time To Live) on a key. The right answer is to always set a TTL on a cache key — SET key value EX 3600 for 1 hour, SET key value PX 60000 for 60 seconds, EXPIRE key 3600 for an existing key. The wrong answer is SET key value with no TTL — the key lives forever, the memory fills up, the eviction policy kicks in, the team’s hot keys get evicted.

Redis Expire: The TTL, the EXPIRE Command, the Key Expiration, and the One Mistake That Fills the Memory

Table of contents

The TTL — the right way to set an expiry

The right answer for a TTL is to set it at the same time as the value: SET key value EX 3600 (1 hour), SET key value PX 60000 (60 seconds), SET key value EXAT 1700000000 (until a specific Unix timestamp). The right answer is to use the right unit — EX for seconds, PX for milliseconds, EXAT for a Unix timestamp in seconds, PXAT for a Unix timestamp in milliseconds.

The EXPIRE command — the right way to set an expiry on an existing key

The EXPIRE command sets a TTL on an existing key: EXPIRE key 3600 (1 hour), PEXPIRE key 60000 (60 seconds), EXPIREAT key 1700000000 (until a specific timestamp). The right answer is EXPIRE when the key exists, the wrong answer is to DEL and re-SET (the team loses the value, the team has a race condition).

The TTL command — the right way to check the remaining time

The TTL command returns the remaining time in seconds (TTL key), PTTL in milliseconds. Returns -1 if the key has no TTL, -2 if the key does not exist. The right answer is to check the TTL before using the key (the team catches the ‘no TTL’ case before the memory fills up).

The PERSIST command — the right way to remove an expiry

The PERSIST command removes the expiry on a key. The right answer is PERSIST to convert a temporary key to a permanent one (a session that needs to outlive the default TTL). The wrong answer is to use PERSIST on a cache key — the team is removing the safety net, the memory fills up.

The eviction policy — the safety net

The eviction policy is what Redis does when the memory is full. The right answer is allkeys-lru for a cache (the least recently used key is evicted), the right answer is volatile-lru for a mixed use (only the keys with a TTL are evicted). The wrong answer is noeviction for a cache — the team gets OOM errors when the memory fills up, the team’s cache stops working.

The right answer is to set the eviction policy in the Redis config (maxmemory-policy allkeys-lru) and the right answer is to set the maxmemory (maxmemory 1gb). The wrong answer is to assume the defaults — the default eviction policy is noeviction.

The one mistake that fills the memory

The mistake: the team runs SET user:1234 <json> with no TTL. The user’s data is updated every request, every request creates a new key, the memory fills up, the eviction policy kicks in, the team’s hot keys (the most-recently-set) get evicted. The right answer is to set a TTL on every key, even the user’s data (SET user:1234 <json> EX 86400 for 24 hours).

The gotcha: the team that uses SETEX key seconds value (the older command) gets the same result as SET key value EX seconds. The right answer is SET ... EX for a new key, the right answer is EXPIRE for an existing key.

The key expiration event — the right answer for cache invalidation

Redis can emit an event when a key expires (__keyevent@0__:expired). The right answer is to subscribe to the event (PSUBSCRIBE __keyevent@*__:expired) and react to the expiration in the application. The right answer is the event for a cache invalidation pattern (the cache entry is the source of truth, the application reacts to the expiration).

The gotcha: the keyspace notifications are off by default (the team has to enable them with notify-keyspace-events in the config). The right answer is to enable the events for the team’s use case, the wrong answer is to assume the events are on.

How this fits the rest of the stack

The infrastructure question is a small piece of a larger pattern: the team’s runtime, storage, database, secret store, logs, and deployment platform are all parts of the same platform. The right answer is to model the full stack before the project ships, not after. The RunxBuild hosting calculator is the right place to do that exercise — pick the runtime, the memory tier, the storage, the secret store, and the egress, and the calculator shows what the deploy actually costs at the team’s actual usage.

Useful related references:

FAQ

How do I set a TTL in Redis?

SET key value EX seconds or SET key value PX milliseconds for a new key. EXPIRE key seconds for an existing key.

What is the difference between EX and PX?

EX sets the TTL in seconds. PX sets the TTL in milliseconds.

What is the default TTL in Redis?

There is no default TTL. A key set with SET key value has no TTL and lives forever. The right answer is to always set a TTL on a cache key.

How do I check the remaining TTL?

TTL key returns the remaining time in seconds, PTTL in milliseconds. Returns -1 if no TTL, -2 if the key does not exist.

How do I remove a TTL?

PERSIST key removes the expiry. The right answer is PERSIST for a key that should outlive the default TTL.

What is the Redis eviction policy?

The policy that Redis follows when the memory is full. allkeys-lru is the right answer for a cache (evict the least recently used). volatile-lru is the right answer for a mixed use (only evict keys with a TTL).

What is the default eviction policy?

noeviction — the team gets OOM errors when the memory is full. The right answer is to set maxmemory-policy allkeys-lru for a cache.

Can I get an event when a key expires?

Yes — enable keyspace notifications (notify-keyspace-events Ex) and subscribe to __keyevent@0__:expired.

#Redis#Expire#TTL#Tutorial#Cache