Design and implement caching strategies across all layers — in-memory, distributed (Redis/Memcached), CDN, HTTP cache headers, and application-level memoization
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Design and implement caching strategies across all layers — in-memory, distributed (Redis/Memcached), CDN, HTTP cache headers, and application-level memoization
["Resource or endpoint to cache","Current latency or load characteristics","Data freshness requirements (real-time, near-real-time, stale-ok)","Infrastructure available (Redis, Memcached, CDN provider, edge)"]
outputs
["Caching strategy document with layer recommendations","Implementation code for chosen cache layer(s)","Cache invalidation plan","TTL and eviction policy recommendations","Monitoring and hit-rate tracking guidance"]
["May add Redis or cache dependencies to project","May modify HTTP response headers","May add middleware or proxy configuration"]
Caching Strategies Skill
Purpose
Caching is the single highest-ROI performance optimization in most systems. This skill designs multi-layer caching strategies, implements them correctly, and — critically — plans cache invalidation so stale data does not become a silent bug.
Key Concepts
The Caching Pyramid (Top = Fastest, Bottom = Slowest)
Is it static content (images, JS, CSS)?
→ CDN + immutable cache headers
Is it per-user, session-scoped?
→ In-memory (server) or browser cache
Is it shared across users, read-heavy?
→ Redis / Memcached with cache-aside
Is it an expensive pure computation?
→ Memoization (in-process LRU)
Is it an API response with known TTL?
→ HTTP Cache-Control headers + stale-while-revalidate
Step 3: Implement
HTTP Cache Headers
// Next.js API route or middlewareexportfunctionGET(request: Request) {
const data = awaitfetchData();
returnResponse.json(data, {
headers: {
// Public: CDN can cache. max-age: browser TTL. s-maxage: CDN TTL.'Cache-Control': 'public, max-age=60, s-maxage=300, stale-while-revalidate=600',
// Vary ensures different cached versions per relevant header'Vary': 'Accept-Encoding, Authorization',
},
});
}
Cache-Control Cheat Sheet:
Directive
Meaning
public
Any cache (CDN, proxy) may store
private
Only browser may store
no-cache
Must revalidate before use (NOT "don't cache")
no-store
Truly never cache
max-age=N
Fresh for N seconds (browser)
s-maxage=N
Fresh for N seconds (shared/CDN cache)
stale-while-revalidate=N
Serve stale for N seconds while refreshing in background
// After a write operation, invalidate related cache keysasyncfunctionupdateUser(userId: string, data: UpdateUserData) {
const updated = await db.user.update({ where: { id: userId }, data });
// Invalidate all cache keys related to this userconst keysToInvalidate = [
`app:user:${userId}`,
`app:user-profile:${userId}`,
`app:user-posts:${userId}`,
];
awaitPromise.all(keysToInvalidate.map((key) => redis.del(key)));
// If using tag-based invalidation (Next.js)revalidateTag(`user-${userId}`);
return updated;
}
Pattern: Versioned Keys
// Instead of invalidating, bump a versionconst version = await redis.incr(`version:user:${userId}`);
const cacheKey = `user:${userId}:v${version}`;
// Old versions naturally expire via TTL
Step 5: Monitor Cache Health
Key metrics to track:
Hit Rate: Target > 90% for most caches
Miss Rate: Spikes indicate cold cache or invalidation storms
Eviction Rate: High evictions = cache is too small
Dogpiling — Multiple processes try to rebuild the same cache entry. Fix: Probabilistic early expiration or mutex.
Over-caching — Caching data that changes frequently, leading to stale reads. Fix: Measure read:write ratio first.
Key Explosion — Unique keys per request parameter combo. Fix: Normalize and limit key cardinality.
Examples
Example 1: E-commerce Product Page
Layer 1: CDN (Vercel Edge) — Cache full HTML for 60s, stale-while-revalidate 300s
Layer 2: Redis — Cache product data for 5 min, invalidate on admin update
Layer 3: DB query cache — Materialized view for price calculations, refresh every minute
Invalidation: Webhook from CMS triggers revalidateTag('product-{id}')
Example 2: User Dashboard (Personalized)
Layer 1: Browser — Cache-Control: private, max-age=0, must-revalidate (no shared cache)
Layer 2: Redis — Cache per-user dashboard data for 30s
Layer 3: In-memory — LRU cache for user preferences (small, rarely changes)
Invalidation: Write-through on user action, TTL expiry for background data
Example 3: Public API with Rate Limits
Layer 1: CDN — Cache GET responses for 10s with Vary: Authorization
Layer 2: Redis — Cache API responses per unique query hash for 60s
Rate limit: Use Redis INCR with TTL for sliding window rate limiting
Invalidation: Short TTLs only — no explicit invalidation needed