Stage 4 · Provision
Cache Design Patterns
Invalidation Strategies
Purge APIs, versioned objects, write-through updates, and event-driven invalidation pipelines.
Why Cache Invalidation?
Cache invalidation is the process of removing stale data from caches when the underlying data changes. Phil Karlton said there are only two hard things in computer science: cache invalidation and naming things. Getting invalidation right is critical for data correctness.
TTL-Based Invalidation
The simplest strategy: set a TTL on every cached entry. After the TTL expires, the entry is automatically removed. The next read fetches fresh data. TTLs are a safety net — even if active invalidation fails, stale data eventually expires.
# Product data: changes occasionally
redis.setex(f"product:{id}", 300, json.dumps(product)) # 5 minutes
# Session data: changes frequently
redis.setex(f"session:{id}", 1800, json.dumps(session)) # 30 minutes
# Configuration: rarely changes
redis.setex("config:features", 3600, json.dumps(features)) # 1 hourSet TTLs based on how frequently data changes. Product data changes occasionally — 5 minutes is fine. Session data changes frequently — 30 minutes is appropriate.
Purge API
CDNs and caches provide purge APIs for instant invalidation. Use them when you need immediate consistency. Purge by URL, by tag, or by surrogate key. Purge operations are fast (sub-second) but limited in rate.
# CloudFront: Create invalidation
aws cloudfront create-invalidation \
--distribution-id E1234567890 \
--paths "/api/products/*" "/static/images/*"
# Fastly: Purge by surrogate key
curl -X POST https://api.fastly.com/service/SERVICE_ID/purge_all
# Cloudflare: Purge by URL
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
--data '{"files":["https://example.com/api/products/123"]}'CDN purges propagate globally within seconds. Use wildcard purges (/api/products/*) to invalidate entire sections. Rate limits apply — do not purge more than once per second.
Versioned URLs
Versioned URLs include a version or content hash in the URL. When the content changes, the URL changes. Old URLs naturally expire from cache. This eliminates the need for active invalidation for static assets.
Static assets:
/static/main.a1b2c3d4.js (content hash in filename)
/static/styles.e5f6g7h8.css (content hash in filename)
API versioning:
/api/v1/products (major version in path)
/api/v2/products (breaking change = new version)
Image transforms:
/images/photo.jpg?w=800&v=2 (version param for transforms)Content hashes in filenames make cache invalidation automatic. Deploy new code, and the new URL gets a fresh cache entry. The old URL expires naturally.
Event-Driven Invalidation
Event-driven invalidation uses events to trigger cache invalidation. When data changes, an event is published. Cache invalidation consumers listen for these events and invalidate the corresponding cache entries.
Database Write
│
▼
CDC (Debezium) ──► Kafka ──► Cache Invalidation Consumer
│
├── Invalidate Redis key
├── Purge CDN by surrogate key
└── Invalidate local cachesCDC captures database changes and publishes events. Cache invalidation consumers listen for these events and invalidate all cache layers. This provides near-real-time consistency.
CDC-Based Invalidation
CDC-based invalidation is the most reliable approach for distributed caches. It captures every database change and propagates it to all cache layers. This eliminates the dual-write problem and ensures all caches stay in sync.
TTLs alone cause stale reads. Use active invalidation (CDC, events, purge API) as your primary strategy and TTLs as a safety net. This ensures both freshness and resilience.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.