Caching Strategies & Layer Placement
How modern web applications serve 95%+ of incoming traffic in under 1 millisecond. Master Cache-Aside, Write-Through, Write-Back, LRU eviction, and the 3 classic cache disasters: Penetration, Avalanche, and Thundering Herd.
โก 1. Why Caching is Mandatory (Hardware Physics)
Imagine you're solving math problems at your desk.
If you keep key formulas on a sticky note on your desk (RAM Cache), glancing at it takes 0.5 seconds. If you have to walk down to the basement library (Disk Database) every single time you need a formula, it takes 15 minutes!
In computers, reading data from RAM is over 100,000ร faster than reading from persistent disk storage:
๐ 2. The 5 Cache Placement Tiers in Production
Where can you place caches between the user's phone and your database? There are 5 distinct layers:
Cache-Control: max-age=3600). Latency = 0ms!๐ 3. The 4 Classic Read & Write Caching Patterns
How should your application coordinate reads and writes between the cache and the primary database?
The application checks the cache first. If found (Hit), return it. If missing (Miss), fetch from DB, save into Cache, and return to user.
The application treats the cache as the main database. When writing data, the cache synchronously updates the database before returning success.
The application writes only to Cache and gets an instant 0.5ms ACK. The cache asynchronously batches writes and flushes them to the DB in the background.
Writes bypass the cache completely and write straight to the database. Only when that data is read later does it enter the cache.
๐ฅ 4. The 3 Classic Distributed Cache Disasters (Interview Favorites)
In high-scale production, three specific failure modes can bring down your entire data infrastructure. Here is how they happen and how senior engineers prevent them:
The Attack: A bot sends 100,000 requests/sec for non-existent IDs (e.g. GET /user/-99999). Because the key does not exist in Redis, every request misses cache and hammers the SQL database directly.
O(1) time, or cache a NULL value with a short 60-second TTL.The Scenario: A viral breaking news article receiving 50,000 requests/sec has its cache key expire at 12:00:00. At that exact millisecond, all 50,000 requests miss cache simultaneously and rush to query the database to rebuild the cache, melting the DB.
SETNX) so only one thread queries the DB to rebuild the cache while all others wait.The Scenario: At midnight, an e-commerce platform caches 500,000 products with a fixed TTL = 2 hours (7200s). At exactly 2:00:00 AM, all 500,000 keys expire at the same second. An avalanche of requests crashes the database.
TTL = 7200 + rand(0, 300). This scatters expiration smoothly over a 5-minute window!๐ป 5. Production Cache-Aside with Mutex Lock (Thundering Herd Defense)
Below is the production implementation of Cache-Aside with a Mutex Lock to prevent Thundering Herd spikes:
// Python 3.10+ Cache-Aside with Mutex Lock (SETNX) import time, random class CacheManager: def __init__(self, redis_client, db_client): self.redis = redis_client self.db = db_client def get_product(self, product_id: str) -> str: cache_key = f"prod:{product_id}" val = self.redis.get(cache_key) # 1. Cache HIT if val is not None: return val # 2. Cache MISS: Acquire distributed lock to prevent Thundering Herd lock_key = f"lock:{product_id}" if self.redis.set(lock_key, "1", nx=True, ex=5): try: val = self.db.query_product(product_id) # Add random TTL jitter (3600s + rand) to prevent Cache Avalanche ttl = 3600 + random.randint(0, 300) self.redis.set(cache_key, val, ex=ttl) return val finally: self.redis.delete(lock_key) else: # Another thread is rebuilding cache; sleep 50ms and retry time.sleep(0.05) return self.get_product(product_id)
๐งช 6. Interactive Lab: Live Cache & Thundering Herd Simulator
Interactive Cache Pattern & Thundering Herd Lab
๐ฏ 7. Test Your Understanding
A breaking news article receiving 50,000 requests/second has its cache key expire. Within 500ms, the primary SQL database crashes with CPU at 100%. What disaster happened and what is the fix?
When a user updates their profile in the database, why do production distributed systems DELETE the cache key rather than UPDATING it in place?