Question presented to candidate: "You cache a user's profile data to avoid a repeated database query, but the user updates their profile five minutes later. How does your cache avoid serving the old, now-wrong data forever?"
What a strong answer should cover:
- Caching stores an expensive-to-compute or expensive-to-fetch result, keyed by its input, so a repeated request for the identical input can be served from memory instead of redoing the work — verified with real measured timing (an identical computation dropping from 104ms to 0ms) in the dedicated performance-techniques question.
- 📌 The core problem the prompt's scenario raises, and its standard fix: a cache with no expiration or invalidation strategy will happily serve stale data forever. A TTL (time-to-live) is the simplest fix — verified directly: a cached value read correctly immediately after being set, and the identical key read again after its TTL had genuinely elapsed correctly returned nothing, forcing a fresh fetch.
- Beyond a blind TTL, explicit invalidation (deleting or updating the cached entry the moment the underlying data actually changes — e.g. when the profile update itself is saved) is more precise than waiting out a TTL, at the cost of needing to remember to invalidate at every single write path that could make the cached value stale.
- Where the cache lives matters for correctness at scale: an in-process cache (a plain
Map) is fastest but is not shared across multiple processes/instances (covered in the dedicated clustering question, with real proof that each worker process has genuinely separate memory) — a shared external cache (Redis) is required when multiple processes/instances must see the same cached state consistently. - A precise answer distinguishes cache-aside (the application checks the cache, falls back to the source on a miss, then populates the cache — the pattern demonstrated directly here) from a write-through cache (updated proactively at write time, alongside the source of truth) — genuinely different strategies for keeping the cache correct, not interchangeable details.
- The honest trade-off, stated explicitly: caching trades some staleness risk for speed — the right TTL/invalidation strategy depends entirely on how tolerable a temporarily-stale value actually is for that specific piece of data, which is a product/business decision as much as a technical one.
Clarifying questions expected:
- "How tolerable is briefly-stale data for this specific value — seconds, minutes, or never?" — directly decides the TTL/invalidation strategy.
- "Does this cache need to be consistent across multiple processes/instances, or is in-process sufficient?" — decides between a local
Mapand an external store like Redis.
Code / implementation expected: Yes — a real TTL-based cache, verified actually expiring a value after its real elapsed time, is the concrete, convincing demonstration of the prompt's exact staleness concern being handled correctly.