All guides

LEARN \u00b7 DEBUGGING GUIDE

Redis cache serving stale data: how to debug it

You update a record in the database. The API still returns the old value. The Redis cache does not know the data changed.

IntermediateCache/queue/distributed bugs

What this usually means

Caches work by storing a copy of data and serving it quickly. They become stale when the source of truth changes but the cache is not updated or invalidated. The cache does not know the data changed — something must tell it. If the invalidation logic has a bug (wrong key, wrong timing, missing call), the stale copy lives until its TTL expires.

( 01 )Fast diagnosis

The first ten minutes \u2014 establish facts before touching code.

  • 1Check if the cache key used for invalidation matches the key used for reads. A subtle difference (extra prefix, different separator) means invalidation targets a different key.
  • 2Verify the invalidation code actually runs. Add a log line or counter. You might find the invalidation call is behind a feature flag, in a skipped code path, or in an error handler that never triggers.
  • 3Check the TTL. If data updates every 5 minutes but the cache TTL is 1 hour, the cache is stale by design — not a bug. Shorten the TTL or add active invalidation.
  • 4Look for a race condition: the cache is populated from a stale read replica while the write goes to the primary. The cache gets old data before replication catches up.
  • 5Check if multiple services write to the same cache key. One service might cache data and another updates the database but does not know about the cache.
( 02 )Where to look

The specific files, logs, configs, and dashboards that usually own this bug.

  • searchCache invalidation code — the function that deletes or updates cache entries after a write
  • searchCache key generation logic — how keys are built for reads vs writes
  • searchDatabase write path — find every place data is updated and check if the cache is invalidated
  • searchRedis CLI or dashboard — inspect the actual keys and values in Redis
  • searchApplication logs — trace a single write operation and see if the cache invalidation log appears
  • searchCache TTL configuration — per-key or global TTL settings
( 03 )Common root causes

Practical causes, not theory. These are the things you will actually find.

  • warningCache invalidation is called with a slightly different key than the read key
  • warningThe invalidation code runs after a successful write but the call is not awaited — it fails silently
  • warningMultiple instances of the app share a cache but only one instance invalidates on write
  • warningDatabase replication lag — the cache is populated from a lagging read replica
  • warningA background job updates the database but no invalidation is triggered
  • warningTTL is too long relative to the data change frequency
  • warningCache is populated at app startup and never refreshed
( 04 )Fix patterns

Concrete fix directions. Pick the one that matches your root cause.

  • buildUse a consistent cache key naming convention — same function generates keys for reads and writes
  • buildAdd cache invalidation to every write path that modifies cached data — make it non-negotiable
  • buildUse a write-through pattern: update the cache at the same time as the database
  • buildReduce TTL to a value shorter than the acceptable staleness window
  • buildAdd a version prefix to cache keys so you can bulk-invalidate by incrementing the version
  • buildUse Redis pub/sub or keyspace notifications to invalidate caches across multiple app instances
( 05 )How to verify

A fix you cannot prove is a guess. Close the loop.

  • verifiedUpdate a record, then immediately query the API. Confirm the response reflects the update.
  • verifiedCheck Redis directly: `GET <key>` before and after the update. The value should change or the key should be deleted.
  • verifiedWrite an integration test that writes, reads from cache, updates the source, and reads again — assert freshness.
  • verifiedMonitor cache hit rate and stale read rate over time. A drop in hit rate after fixing invalidation is expected and healthy.
  • verifiedSimulate a deployment with multiple app instances and verify cache consistency across all instances.
( 06 )Mistakes to avoid

Things that make this bug worse or harder to find.

  • warningSetting an extremely short TTL to 'fix' staleness — it causes cache stampedes under load
  • warningInvalidating the entire cache instead of specific keys — this causes thundering herd problems
  • warningAdding invalidation only to some write paths and forgetting others
  • warningAssuming the cache layer will magically stay in sync without explicit invalidation
  • warningNot monitoring cache staleness — you will not know it is broken until users complain