Cache is the most effective way to speed up an application. But poor cache invalidation is one of the hardest problems in CS.
Strategies¶
- Cache-aside: Application reads/writes cache explicitly
- Write-through: Write to cache and DB simultaneously
- Write-behind: Write to cache, async to DB
- Read-through: Cache automatically loads from DB
HTTP Cache Headers¶
Static assets — long cache¶
Cache-Control: public, max-age=31536000, immutable
API response — short cache¶
Cache-Control: private, max-age=60
Validation with ETag¶
ETag: “abc123” If-None-Match: “abc123” # 304 Not Modified
Cache-Aside Pattern¶
async def get_product(product_id):
1. Check cache¶
cached = await redis.get(f”product:{product_id}”) if cached: return json.loads(cached)
2. Cache miss — fetch from DB¶
product = await db.products.find(product_id)
3. Store in cache¶
await redis.setex(f”product:{product_id}”, 3600, json.dumps(product)) return product
Key Takeaway¶
Cache-aside for most use cases. HTTP cache headers for CDN. Invalidation is harder than it seems — TTL is the simplest approach.