Microservices Caching Strategies
Reading from a database takes milliseconds. Reading from memory takes microseconds. A cache keeps copies of frequently requested data in fast storage so services answer quickly and databases rest. In a system of many services, smart caching cuts latency, saves money, and absorbs traffic spikes.
Layman Explanation
A chef keeps salt, oil, and pepper on the counter without walking to the pantry for every dish. Counter space is small, so only frequent items sit there. A cache holds the popular data close to the code.
Where Caches Live
Client Cache
Browsers and apps store responses locally. HTTP headers such as Cache-Control tell the client how long a copy stays fresh.
Edge Cache or CDN
A content delivery network stores images, scripts, and public pages near the user. Distance shrinks and load on origin servers drops.
Gateway Cache
The API gateway stores replies to popular read requests, which spares the services behind it.
Service-Level Cache
A service keeps data in its own memory or in a shared store such as Redis. This layer gives the biggest gains for database-heavy reads.
Diagram: Layers of Cache
User --> Browser cache --> CDN --> Gateway cache --> Service --> Redis --> Database
(hit? stop) (hit?) (hit?) (hit?)
Each layer that answers saves a trip to the layers on the right.
Core Patterns
Cache-Aside
The service checks the cache first. On a miss, it reads the database, stores the result in the cache, and returns it. Most teams start here because it is simple and works with any store.
read(product 42):
value = cache.get("product:42")
if value is empty:
value = database.read(42)
cache.set("product:42", value, ttl = 300 seconds)
return value
Write-Through
Every write goes to the cache and the database together. Reads always find fresh data, at the cost of slower writes.
Write-Behind
The service writes to the cache and saves to the database later in batches. Writes feel fast, though a cache crash can lose recent changes.
Expiry and Invalidation
Stale data causes confusion. Two tools keep it under control:
- Time to live, or TTL, removes entries after a set period.
- Event-based invalidation deletes an entry when the owning service publishes a change event.
A famous saying among engineers states that cache invalidation is one of the two hard problems in computing. Short TTLs plus change events handle most real cases.
Common Problems
Cache Stampede
A popular entry expires and hundreds of requests hit the database at once. Locks, request coalescing, and slightly randomized TTLs prevent the pile-up.
Cache Penetration
Requests for missing keys always bypass the cache. Store a short-lived "not found" marker to stop repeated database hits.
Stale Reads
Users briefly see old values. Accept this for catalogs and feeds, and avoid caching for balances and stock counts that demand precision.
What to Cache
| Good Candidates | Poor Candidates |
|---|---|
| Product details | Live account balances |
| Configuration values | One-time tokens |
| Search results | Highly personal, rapidly changing data |
Measuring Cache Success
Track the hit ratio, which equals hits divided by total requests. A ratio above 90 percent on read-heavy data signals a healthy cache. Watch memory use, eviction counts, and response times too. Low hit ratios mean wrong keys, short TTLs, or data that does not suit caching.
Key Takeaways
Caching trades freshness for speed. Choose layers wisely, start with cache-aside, set sensible expiry rules, and guard against stampedes.
