Community content. Review instructions before giving them to an AI agent — treat modules like open-source code.
Caching Strategy Rules
Apply a disciplined caching strategy: cache-aside as the default pattern, TTLs on everything, explicit invalidation on writes, stampede protection, versioned cache keys, what to never cache, and measuring hit rates.
Mby @markdownersPublished August 21, 2026 · ~3 min read
0 downloads · Used by 0 stacks
Every cache is a second copy of the truth that can drift from the first — default to cache-aside with an explicit invalidation path for every write, and treat "how does this entry get removed or refreshed" as a mandatory design question for every cache you add, not an afterthought.
Default pattern
- Use cache-aside (read: check cache, on miss read the source and populate the cache; write: write the source, then invalidate or update the cache) as the default pattern — it's the simplest to reason about and keeps the cache strictly a derived, disposable copy of the source of truth.
- Never make the cache the only copy of data that matters — a cache must always be safely droppable and rebuildable from the source without data loss; if losing the cache would lose real data, it isn't a cache, it's a database with an availability problem.
TTL on everything
- Set an explicit TTL on every cache entry, even ones you believe will be actively invalidated on every relevant write — invalidation logic has bugs, deploys miss an invalidation path, and a TTL is the backstop that guarantees staleness is bounded even when explicit invalidation fails.
- Choose the TTL based on how stale the data is allowed to be for its actual use case, not a single global default — a public content page can tolerate minutes of staleness; a per-user permission check usually cannot.
Invalidation
- Invalidate (or update) the relevant cache entries synchronously as part of the write path, in the same request/transaction where practical — invalidation that happens "eventually" via a separate async process reintroduces the staleness window you were trying to avoid.
- Invalidate by the same key structure used to populate the cache — if reads key by
user:{id}:profile, the write path for that user must invalidate exactly that key (or a superset), not a guess at what might be cached. - When one write affects many cache entries (a tag or category change affecting every item in it), use a versioned or grouped invalidation strategy (a version number embedded in the key, a tag-based cache) rather than trying to enumerate every affected key by hand.
Stampede protection
- Protect hot keys from cache stampede (many concurrent requests missing the same expired key and all hitting the source simultaneously) with a lock, request coalescing, or a "probabilistic early expiration" that refreshes before the TTL fully expires — an unprotected stampede can take down the source the cache exists to protect.
- Prefer serving slightly stale data for a brief window while one request refreshes the cache, over letting every concurrent request hit the source — staleness is usually cheaper than a thundering-herd outage.
Cache keys
- Include a version segment in cache keys tied to the data shape or serialization format (
v2:user:{id}) — this lets a deploy that changes what's cached invalidate everything at once by bumping the version, instead of needing a flush-everything migration step. - Make keys deterministic and fully derived from their inputs (including any relevant filter/sort/locale parameters) — two logically different requests must never collide on the same key, and the same logical request must always produce the same key.
What never to cache
- Never cache data that's used for authorization or security decisions (permission checks, entitlements) unless the invalidation path is airtight and the TTL is very short — a stale "yes you're allowed" is a security bug, not a performance tradeoff.
- Never cache highly personalized responses under a shared key — caching a per-user response under a key that doesn't include the user id serves one user's private data to another.
Measuring effectiveness
- Track cache hit rate per cache/key-pattern, not just in aggregate — a cache that's globally 90% hit rate can still be nearly useless for the one hot path that actually needed it if that path's own hit rate is low.
- Revisit or remove caches whose hit rate doesn't justify their invalidation complexity — a cache that's rarely hit but frequently invalidated is net-negative: all the correctness risk, none of the performance benefit.
Badge
Link back to this module from your own README.
[](https://markdowners.com/m/markdowners/caching-strategy-rules)Discussions about this module
No discussions about this module yet.
Start a discussion
Comments (0)
Sign in to comment. Sign in
No comments yet. Be the first to add one.