Cache
A fast side store that remembers expensive answers so you skip the slow work next time. Great until it hands back stale data.
See it
What it is
A cache is a fast store that keeps the answer to an expensive question so you do not have to ask again. Request comes in, you check the cache first (a 'hit' returns in a millisecond), and only on a 'miss' do you hit the database or the third-party API and then write the result back. Redis and Memcached are the usual boxes; an in-process Map, HTTP cache headers, and your framework's data cache are all the same idea at different distances.
Reach for it when the same expensive result is read far more often than it changes: a dashboard aggregate, a pricing table, a rendered marketing page, a rate-limit counter. The two knobs that matter are the key (make it specific enough that user A never sees user B's data, which means user id and locale go in the key) and the TTL, the time to live after which the entry expires on its own.
Caching is easy; invalidation is the hard part, and stale data is the bug users report as 'I saved it but it still shows the old name'. Pick a strategy up front: short TTL, or explicit deletion of the key on write. Deleting on write shrinks the stale window, it does not close it, because a reader that missed a moment earlier can still finish its slow database read and write that now-old value back after your delete. When freshness is actually mandatory, stop invalidating and start versioning: put an updated_at or version counter in the key so a write simply points readers at a new key, or write through the cache under a lock so the fill and the update cannot interleave. Also watch for the thundering herd, where a popular key expires and 5,000 requests all miss and stampede the database at once. Lock the refresh or stagger the TTLs with a little jitter.
Ask AI for it
Add a Redis cache in front of this expensive read. Use a cache-aside pattern: build a namespaced key that includes every input that changes the result (resource id, user or tenant id, locale, version), check the cache, and on a miss fetch, store with a TTL, and return. Set the TTL from how stale this data may safely get and add random jitter so keys do not all expire at once. Explicitly delete or overwrite the key in the write path to cut the stale window, and note in a comment that this narrows staleness rather than eliminating it, since a concurrent fill can repopulate an old value just after the delete. If this data must never be served stale, use a version or updated_at segment in the key so writes publish a new key instead, or write through the cache under a lock. Fail open: if Redis is down, log it and fall through to the database instead of erroring.