~12 min
A TTL (time-to-live) is the simplest invalidation strategy available: attach an expiry to a cache entry when it's written, and let it disappear on its own rather than trying to explicitly invalidate it from every place the underlying data could change. Redis's own documentation on EXPIRE is specific about which operations respect that boundary: the timeout is cleared only by commands that delete or overwrite a key's contents outright — DEL, SET, GETSET, the *STORE commands — while an operation that alters the value without replacing it, like INCR on a counter or HSET on one field of a hash, leaves an existing timeout untouched. That distinction matters in practice: a cache entry given a TTL and then incrementally updated with a field-level command keeps counting down to the same deadline — it doesn't reset.
A TTL bounds staleness, but it doesn't bound memory — a cache can still fill up before anything expires. That's what an eviction policy is for: Redis's documentation lists several, and picking the right one is a match to the access pattern, not a default you leave alone. allkeys-lru evicts whichever key hasn't been touched in the longest time, which fits a workload where a subset of keys stays popular and the rest fades; allkeys-random fits a workload where keys are read in a roughly even, cyclical pattern, where recency carries no signal at all; volatile-ttl evicts whichever key with an expiry is closest to expiring anyway, which the documentation suggests specifically when the application can already estimate which keys are good candidates for early eviction. The volatile-* policies only ever touch keys that were given a TTL in the first place — a key with no expiry is untouchable to them, no matter how memory-starved the cache gets.
Yes — HSET alters the hash without overwriting the whole key, so per Redis's own documentation it leaves an existing timeout untouched.