The two sentinels
-1 and -2 are replies, not durations, and mean very different things
3600 -1 -2
Paste TTL values, either bare numbers or durations like 3d, and get milliseconds, seconds, a human reading and the commands that set them. The two sentinel replies are called out rather than converted.
TTL returns seconds, PTTL returns milliseconds. A duration like 3d or 90m is understood whichever is selected.
Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.
The answer appears here
Paste on the left and press Convert. Nothing leaves this tab.
Nothing else to flag.
No formatting problems, and nothing the rules object to. Worth remembering what that covers: this reads the file you pasted, not the account or cluster it will be applied to.
No finding matches that filter.
Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.
-1 and -2 are replies, not durations, and mean very different things
3600 -1 -2
A duration converted to the EXPIRE and PEXPIRE calls that set it
3d 90m 12h
These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
They are sentinels. -1 means the key exists with no expiry and -2 means it does not exist, so a dashboard averaging TTLs quietly folds negative numbers into the mean.
Instead:Filter them out and count them separately. They answer a different question from a remaining lifetime.
SET clears an existing expiry. A refresh path written this way silently makes keys permanent, which shows up as a cache that stops evicting and grows.
Instead:SET ... KEEPTTL to preserve it, or SET ... EX to set both atomically.
If the process dies between them the key exists with no TTL, forever. It is also two round trips.
Instead:SET key value EX seconds does both atomically in one call.
A positive reply is a remaining lifetime. The two negative replies are not lifetimes at all, and treating them as numbers is how a monitoring dashboard ends up with a negative average TTL.
Usually this is intentional. When it is not, the cause is almost always a plain SET: SET overwrites a key's expiry, so a code path that refreshes a value with SET rather than SET ... KEEPTTL silently makes it permanent. PERSIST does the same thing deliberately.
It may have expired, it may have been evicted under maxmemory pressure, or it may never have been written. TTL cannot distinguish those, and neither can EXISTS. Eviction and expiry look identical from the outside, which is why an unexplained -2 usually needs the INFO stats for evicted_keys and expired_keys to resolve.
Sub-second lifetimes need PEXPIRE. EXPIRE rounds, so a value under a second becomes zero or one rather than what you meant. Setting a key and its expiry in one call with SET key value EX or PX is both fewer round trips and atomic, which matters because a SET followed by a separate EXPIRE can leave a permanent key if the process dies between them.
A key with a past expiry is not deleted at that instant. Redis removes it when something touches it, and separately samples random keys twenty times a second to expire a fraction of those found dead. So a key can be logically gone while still occupying memory, which is why memory does not drop the moment a large batch of TTLs passes.
It converts numbers. It does not know when a key was written, so it cannot tell you the absolute time a key expires, and it cannot tell you whether a TTL you are about to set is longer than the key will survive under your eviction policy.