Redis / Editorial solution guide

Diagnose cache misses, expiry, eviction and stale fills

Explain why a key is absent or unexpectedly stale before extending TTL, changing eviction or deleting a namespace. Preserve the authoritative-data and freshness contract.

About 4 min readContent reviewed

Read-only knowledge base · No public comments

Recognize the symptoms

A key disappears before its expected deadline, TTL reports -1 or -2, source traffic spikes, or a value becomes stale again after invalidation. These are not one failure. Expiry, memory eviction, explicit deletion, replacement, namespace mismatch and late stale repopulation can produce similar user-visible misses or wrong reads.

Understand the likely causes

  • Writers may clear expiry with plain SET, attach value and TTL separately, renew unexpectedly or use inconsistent key versions. maxmemory policy can evict an unexpired key. In cache-aside, an older source read can refill stale data after a newer write invalidates the key. Replica/failover and recovery context can add further lifecycle differences, so identify the actual endpoint and key before changing policy.

Confirm exact identity, type and expected lifetime

Record the generated key name, database/topology, owning writer, value schema and intended freshness rule without exposing sensitive values. A naming/version change can create a second cache population, while reading another endpoint can produce a different view. Use metadata only on a known synthetic fixture or through an existing authorized operational path. Do not begin with broad KEYS or a full key/value dump. A missing key is an observed outcome; it does not by itself establish the mechanism that removed or failed to create it.

Interpret metadata and counters separately

TTL -1 means an existing key without expiration and -2 means absence on the stated modern baseline. Positive countdowns vary, so do not infer exact deletion timing from one observation. TYPE and TTL can reveal a type/lifetime mismatch without reading the payload. INFO stats can provide expired/evicted counter context, but counters may reset and are not per-key proof. The example is read-only editorial material and executes no command. Managed products may expose equivalent metrics instead; permission failures do not prove that expiry is broken.

redis Non-runnable known-key lifecycle inspection
TYPE lab:cache:known-record
PTTL lab:cache:known-record
INFO stats

No live values or countdown are supplied. Compare expired_keys and evicted_keys only with the relevant time window and reset context.

Inspect the write path and late-fill schedule

Review whether value and expiry are written atomically, whether plain SET removes an old TTL, and which actor renews or deletes the key. Distinguish genuine authoritative absence from source failure before negative caching. A successful invalidate-after-write can still be followed by a late old-reader fill, so a longer or shorter TTL alone is not a complete correctness repair. Review version/generation eligibility and invalidation delivery under the service contract. Do not add arbitrary delayed deletes and advertise strong consistency without proving the permitted interleavings.

Keep validity independent from storage presence

The offline calculation treats the expiry instant as invalid even if a hypothetical storage entry still exists. It is a local business policy, not a simulation of Redis active/passive expiry or memory reclamation. Authorization-sensitive values must follow their required validity and revocation rules rather than extending life merely to reduce source load. Cache outage and eviction recovery need bounded fallback, coalescing and admission so broad misses do not overwhelm the source. Jitter or stale serving must remain within the declared freshness policy and cannot silently weaken access decisions.

python Offline distinction between presence and validity
def valid_model(now_ms, deadline_ms):
    return now_ms < deadline_ms

entry_still_present = True
assert entry_still_present
assert not valid_model(1000, 1000)
assert valid_model(999, 1000)

The declared item can be physically present yet invalid at its deadline. No Redis timing or key behavior is measured.

Verify the fix

On an isolated fixture, verify create, refresh, replace, invalidate and expiry-boundary cases with the actual client’s encoding. Include the late-fill race and source-error/absence distinction. After the reviewed fix, correlate miss rate, source load, expiry/eviction, stale results and write outcomes rather than accepting a better hit percentage alone.

Keep it from recurring

  • Define lifecycle ownership for each key family, attach TTL atomically where appropriate and keep cache versions explicit. Separate eviction and expiration alerts, bound reload/retry concurrency and maintain a documented freshness policy for sensitive data and negative entries.

Official references