8.2 Caching Strategies and ElastiCache Patterns
Key Takeaways
Lazy Loading (cache-aside) reads cache first, and on a miss reads the database, writes the result to cache, then returns — only requested data is cached but the first read always misses (cold start).
Write-Through writes to cache and database together so cached data is never stale, at the cost of write latency and caching data that may never be read.
TTL (Time-to-Live) bounds staleness and stops unbounded cache growth; pair it with lazy loading + write-through for the recommended combined pattern.
ElastiCache for Redis supports replication, Multi-AZ failover, persistence, sorted sets, pub/sub, and geospatial data; Memcached is multi-threaded, simple, and has no persistence or replication.
Storing sessions in ElastiCache for Redis (or DynamoDB) makes app servers stateless, enabling clean horizontal scaling and removing the need for ALB sticky sessions.
Quick Answer: Lazy loading = cache-aside (check cache; on miss read DB, fill cache, return). Write-through = write cache + DB together (never stale, but write overhead). TTL auto-expires entries. Use Redis for persistence, Multi-AZ failover, sorted sets, and pub/sub; use Memcached for simple multi-threaded key-value caching. Move sessions into Redis to make app servers stateless and scale horizontally.
Caching Strategies
Lazy Loading (Cache-Aside)
- App checks the cache.
- Hit → return cached data (fast).
- Miss → read the database, write the result to cache, return.
| Advantage | Disadvantage |
|---|---|
| Only data that is actually requested is cached | Every cache miss adds a round trip (cold-start latency) |
| A cache node failure does not break the app | Data can go stale (no auto-refresh) |
| Simple to implement | First request for any key always misses |
Write-Through
The app writes to cache AND database on every write, so reads always hit fresh data.
| Advantage | Disadvantage |
|---|---|
| Cached data is never stale | Extra write latency on every update |
| Reads are reliably fast | Caches data that may never be read |
Recommended combined pattern
Use lazy loading + write-through + TTL together: write-through keeps actively updated keys fresh, lazy loading populates read-only keys on demand, and TTL caps staleness and reclaims memory. The exam treats 'minimize stale data' as a write-through signal and 'reduce read latency / offload the database' as a lazy-loading signal.
Choosing a TTL
| Data change rate | Suggested TTL |
|---|---|
| Real-time (stock/ticker) | 5–30 seconds |
| Frequently changing (inventory) | 1–15 minutes |
| Slowly changing (user profiles) | 1–24 hours |
| Rarely changing (config, static) | 1–7 days |
Common Trap: A 'thundering herd' happens when a popular key expires and many requests miss simultaneously and stampede the database. Mitigate with slightly randomized (jittered) TTLs or pre-warming hot keys.
Session Store Pattern
Keeping session state on individual EC2 instances forces ALB sticky sessions and loses carts when an instance fails or scales in.
| Without ElastiCache | With ElastiCache (Redis) |
|---|---|
| Sessions live on each app server | Sessions centralized in Redis |
| ALB sticky sessions required | Any server serves any user |
| Losing a server loses its sessions | Server loss does not lose sessions |
| Uneven load distribution | App servers are stateless → free horizontal scaling |
On the Exam: 'Make app servers stateless for Auto Scaling' → store sessions in ElastiCache for Redis (or DynamoDB). 'Reduce repeated identical database reads' → add ElastiCache with lazy loading.
Redis vs. Memcached
ElastiCache offers three engines: Redis OSS, Valkey (an open-source Redis fork AWS now offers at lower cost), and Memcached. For the exam, the decisive split is Redis-family (rich features) vs Memcached (simple).
| Choose Redis / Valkey when you need… | Choose Memcached when you need… |
|---|---|
| Persistence (snapshots / AOF) | Pure, simple key-value caching |
| Multi-AZ with automatic failover | Maximum simplicity, no failover |
| Read replicas / replication | Multi-threaded scale-up on large nodes |
| Complex types (lists, sets, sorted sets for leaderboards) | Sharded horizontal scaling of plain objects |
| Pub/sub messaging, geospatial, Lua scripting | No persistence requirement |
Key exam tells: leaderboard / ranking → Redis sorted sets; persistence or failover → Redis; simplest possible cache, multi-threaded → Memcached.
Cache Invalidation
| Method | How | Use case |
|---|---|---|
| TTL | Entries auto-expire | General default |
| Explicit delete | App deletes the key on update | Known data changes |
| Event-driven | DynamoDB Streams / SNS / EventBridge updates the cache | Near-real-time consistency |
Beyond ElastiCache
ElastiCache is in-memory caching for application-tier data and sessions. Do not confuse it with DynamoDB Accelerator (DAX), an in-memory cache specific to DynamoDB that requires no application code change, or with CloudFront, which caches HTTP responses at edge locations. A 'cache DynamoDB reads with microsecond latency and no code change' scenario points to DAX, not ElastiCache.
Worked Example: Sizing a Read-Heavy Cache
Suppose a product-catalog page is read 10,000 times per second but the underlying items change only a few times per hour. Without caching, every request hits RDS, forcing a large, expensive instance and read replicas just to survive. Add ElastiCache for Redis with lazy loading and a 5-minute TTL: after the cache warms, the cache-hit ratio approaches 99%, so RDS sees roughly 100 reads/second instead of 10,000. The database can shrink, replication lag disappears, and p99 read latency drops from tens of milliseconds to sub-millisecond. This is the canonical 'reduce database load and latency' answer.
Now contrast a checkout-price scenario where a stale price for even seconds is unacceptable. Here lazy loading alone is risky; pair write-through (update the cache whenever the price is written) with a short TTL as a safety net. The pattern you choose is dictated by the staleness tolerance stated in the question.
Multi-AZ and Failover Details
For Redis, a replication group has one primary and up to five read replicas across AZs. With Multi-AZ enabled, ElastiCache automatically promotes a replica to primary on failure and updates the primary endpoint DNS — typically within seconds. Memcached has no replication or failover; a lost node simply loses its slice of cached data, which is acceptable only for pure caches that can repopulate from the database. If a question demands cache durability or automatic failover, Memcached is eliminated immediately.
| Requirement | Engine answer |
|---|---|
| Automatic failover, replica promotion | Redis Multi-AZ |
| Survive node loss without data loss | Redis with replicas + backups |
| Cheapest pure cache, repopulates from DB | Memcached |
A read-heavy application is adding caching, but the team is most worried about ever serving stale data. Which approach minimizes staleness?
Lazy loading with no TTL
Lazy loading with a long TTL
Write-through caching combined with a TTL
Disable caching and rely only on read replicas
An online game must display a real-time global leaderboard ranking millions of players, with sub-millisecond updates and durable failover. Which ElastiCache choice fits best?
Memcached, because it is multi-threaded
Redis, using sorted sets with Multi-AZ failover
DynamoDB Accelerator (DAX)
CloudFront caching of the leaderboard page
Sections you finish are checked off in the contents.