Caching Strategies — Cheat Sheet

Tags: caching, redis, memcached, cdn, cache-aside, write-through, system-design

Level: intermediate

TL;DR: Guide to common caching patterns, eviction policies, and cache invalidation strategies for scalable backend systems.

Key concepts

Cache-Aside (Lazy Loading): application checks cache first, queries DB on miss, writes result back to cache.

Read-Through: application queries cache abstraction; cache fetches from DB on miss transparently.

Write-Through: data is written to cache and DB synchronously, ensuring consistency but higher write latency.

Write-Back (Write-Behind): data written to cache immediately, DB updated asynchronously in batches.

Write-Around: data written directly to DB, bypassing cache to avoid cache pollution for rarely read data.

Eviction policies define removal rules when memory limits are reached (LRU, LFU, FIFO, TTL).

Cache invalidation options: explicit key deletion on update, time-to-live expiration, or event-driven triggers.

Cache layers span multiple tiers: browser/client, CDN edge, API gateway, application memory, distributed stores.

Typical questions and ready answers

Q: How do you handle cache invalidation in a high-traffic microservices architecture?R: I rely on event-driven invalidation via message brokers on DB updates, paired with defensive TTLs to guarantee convergence and prevent stale state.

Q: What is the difference between Cache-Aside and Write-Through?R: In Cache-Aside, the application manages reads and writes directly between cache and DB; in Write-Through, the cache layer itself handles DB writes synchronously.

Q: How do you protect against cache stampede (thundering herd)?R: I use mutex/distributed locks around DB recomputation, background pre-fetching with early TTL revalidation, or stale-while-revalidate patterns.

Pitfalls and common mistakes

Cache stampede when popular keys expire simultaneously under high read concurrency.

Cache penetration: requests for non-existent keys repeatedly hitting the database; solve with bloom filters or caching null objects.

Cache breakdown: high-traffic hot key expires suddenly, saturating DB; solve with mutex locking or probabilistic early expiration.

Memory exhaustion due to missing TTLs and unbounded key growth.

Inconsistent data caused by race conditions between concurrent DB updates and cache writes.

Snippets and commandsTypeScript

// Cache-Aside pattern implementation
async function getCachedUser(userId: string): Promise<User> {
  const cacheKey = `user:${userId}`;
  const cached = await redis.get(cacheKey);

  if (cached) {
    return JSON.parse(cached);
  }

  const user = await db.users.findById(userId);
  if (user) {
    await redis.set(cacheKey, JSON.stringify(user), 'EX', 3600);
  }

  return user;
}

Bash

# Redis CLI inspection & eviction diagnostics
redis-cli INFO stats | grep -E 'keyspace_(hits|misses)'
redis-cli --bigkeys
redis-cli CONFIG GET maxmemory-policy

To review

[ ] Implement Redis distributed lock for hot key cache repopulation

[ ] Configure bloom filters for cache penetration prevention

[x] Cache-Aside vs Write-Through trade-offs

[x] Eviction policies (LRU, LFU, TTL)

References

Redis Documentation: Memory Optimization and Eviction Policies

System Design Interview – Alex Xu (Chapter: Caching & Scalability)

Jarvis Interviews
Jarvis