The default that clears a TTL
No expiry and no KEEPTTL, so an existing expiry is discarded
- key
- session:abc
- value
- hello
- expiry
- ttl-seconds
Build a SET with its options. The one that catches people: a SET without an expiry and without KEEPTTL removes whatever TTL the key already had, silently, so a cache entry becomes permanent.
Worked setups you can load into the form above. Each one is a decision the generator makes differently, and the reason it makes it.
No expiry and no KEEPTTL, so an existing expiry is discarded
SET NX with an expiry, and why releasing it needs more than DEL
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
It does not. The expiry is discarded and the key becomes permanent.
Instead:Pass KEEPTTL, or set the expiry again.
If your lock already expired, DEL removes whoever holds it now.
Instead:Use a Lua compare-and-delete against your token.
Two commands are not atomic, so the process can die between them and leave a key with no expiry.
Instead:One SET with NX and EX together.
It is a syntax error before Redis 7.0.
Instead:Check the server version, or use a script.
It is the first command anybody learns and it has four options whose interaction decides whether data expires, whether a write is atomic, and whether it works at all on your server version.
Rewriting a key with SET discards its TTL unless you pass KEEPTTL or set a new expiry. A key that was expiring in an hour becomes permanent. There is no error and no warning, and on a cache it means the key is never reclaimed until eviction pressure removes it.
Acquiring is easy. The failure is releasing a lock that already expired and was taken by somebody else, because a plain DEL then deletes the other holder's lock. The release has to be a compare-and-delete that checks the value still matches your own token, which means a Lua script.
Before 7.0 the server rejected that combination as a syntax error. It is genuinely useful, because it tells you the existing value in the same round trip in which your write was refused.
EX is relative to now, so recomputing a duration on every write lets the expiry drift forward indefinitely. EXAT takes a Unix timestamp and does not drift.
They still work and are not being removed. SET with options does everything they do and can combine an expiry with a conditional set in one atomic command, which they cannot.