π Caching - Redis, Memcached, & CDNs
There are only two hard things in Computer Science: cache invalidation and naming things. A Programmer treats the cache as an optimization, not a source of truth, and always designs a system that can function (albeit slowly) if the cache layer disappears.
ποΈ The Caching Layers
Section titled βποΈ The Caching Layersβ1. Client-Side / Browser Caching
Section titled β1. Client-Side / Browser CachingβUses HTTP headers (Cache-Control, ETag) to store assets directly on the userβs device.
- Best for: Static assets (JS, CSS, Images).
2. CDN (Content Delivery Network)
Section titled β2. CDN (Content Delivery Network)βEdge servers distributed globally (Cloudflare, Akamai, AWS CloudFront).
- Best for: Static and semi-static content. It reduces latency by serving data from the server physically closest to the user.
3. Distributed Cache (Redis vs. Memcached)
Section titled β3. Distributed Cache (Redis vs. Memcached)βIn-memory data stores sitting between your App and your Database.
- Memcached: Simple, multi-threaded, best for large, static objects.
- Redis: Single-threaded but rich in data structures (Lists, Sets, Hashes, Pub/Sub). The industry standard for most modern apps.
π οΈ Caching Strategies
Section titled βπ οΈ Caching StrategiesβCache-Aside (Lazy Loading)
Section titled βCache-Aside (Lazy Loading)βThe application code checks the cache first. If itβs a miss, it queries the DB, stores the result in the cache, and returns.
- Pros: Resilient to cache failure.
- Cons: First request is always slow; data can become stale if the DB is updated directly.
Write-Through
Section titled βWrite-ThroughβThe application writes data to the cache and the DB simultaneously.
- Pros: Cache is never stale.
- Cons: Higher write latency.
Write-Behind (Write-Back)
Section titled βWrite-Behind (Write-Back)βThe application writes to the cache only. A background process syncs the cache to the DB later.
- Pros: Incredible write performance.
- Cons: High risk of data loss if the cache crashes before the sync.
βοΈ Managing Cache Invalidation
Section titled ββοΈ Managing Cache InvalidationββStale dataβ is the biggest risk in caching. You need a strategy to clear the cache when data changes.
- TTL (Time To Live): Setting an expiration time. A simple βsafety netβ but doesnβt guarantee immediate consistency.
- Event-based Invalidation: Using your Event-Driven Architecture to purge or update cache keys when a specific event (e.g.,
ProductUpdated) occurs. - Versioning: Changing the key name (e.g.,
user_123_v1touser_123_v2) to force a fresh fetch.
π© Challenges: The βEdge Casesβ
Section titled βπ© Challenges: The βEdge Casesββ1. Cache Penetration
Section titled β1. Cache PenetrationβWhen requests for non-existent data hit the DB because the cache doesnβt have it.
- Solution: Cache βnullβ results with a short TTL or use a Bloom Filter to check if a key exists before hitting the cache/DB.
2. Cache Stampede (Thundering Herd)
Section titled β2. Cache Stampede (Thundering Herd)βWhen a high-traffic key expires, and thousands of concurrent requests all hit the DB at once to re-cache it.
- Solution: Use Locking (only one request goes to the DB, others wait) or External Re-computation (a background job refreshes the cache before it expires).
3. Hot Keys
Section titled β3. Hot KeysβWhen a single cache node is overwhelmed because one specific key (e.g., a viral post) is requested millions of times.
- Solution: Use Local In-Memory Caching (in the application process) for the most popular keys or replicate the hot key across multiple cache nodes.
π Comparison: Redis vs. Memcached
Section titled βπ Comparison: Redis vs. Memcachedβ| Feature | Redis | Memcached |
|---|---|---|
| Data Types | Strings, Hashes, Lists, Sets, Geospatial | Strings / Blobs only |
| Persistence | Yes (RDB/AOF) | No (In-memory only) |
| Architecture | Single-threaded (mostly) | Multi-threaded |
| Scaling | Redis Cluster | Client-side sharding |
| Best For | Complex logic, Pub/Sub, Persistent state | Simple, high-speed object caching |
π‘ Note: Before implementing a distributed cache, check your Database Indexes. A common junior mistake is trying to βfixβ a slow database with Redis, when a simple index on the table would have solved the problem at its source without adding more infrastructure.