DEV Community

Cover image for Caching Strategies: A Senior Engineer's Guide
Arghya Majumder
Arghya Majumder

Posted on

Caching Strategies: A Senior Engineer's Guide

Caching Strategies: A Senior Engineer's Guide

A comprehensive guide to caching at every layer — from browser to CDN to database — for system design interviews.


1. Client-Side: The "Edge of the Edge"

At a senior level, client-side caching isn't just about localStorage; it's about interception and background synchronization.

Service Workers (The Programmable Proxy)

Service Workers live between the browser and the network, allowing you to implement complex caching logic.

// Stale-While-Revalidate pattern
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.open('v1').then(async (cache) => {
      const cachedResponse = await cache.match(event.request);

      // Fetch fresh data in background
      const fetchPromise = fetch(event.request).then((response) => {
        cache.put(event.request, response.clone());
        return response;
      });

      // Return cached immediately, update in background
      return cachedResponse || fetchPromise;
    })
  );
});
Enter fullscreen mode Exit fullscreen mode

Strategy by Request Type

Use request.destination to apply different strategies:

Destination Strategy Example
font Cache-Only Self-hosted web fonts (never change)
image Cache-First Product images, logos
document Network-First HTML pages (need fresh content)
fetch (API) Network-First Real-time stock/API data

Browser HTTP Cache

Controlled by Cache-Control headers.

Fingerprinting Strategy:

# Immutable assets with hash in filename
main.a4f2b3c.jsCache-Control: max-age=31536000, immutable

# HTML files (need revalidation)
index.htmlCache-Control: no-cache
Enter fullscreen mode Exit fullscreen mode

Result: Users only download core platform logic once per release.


2. Networking & Infrastructure Layers

This is where you manage the "Thundering Herd" problem and geographical latency.

The Caching Hierarchy

┌─────────────────────────────────────────────────────────────┐
│  Browser Cache                                              │
│  └─▶ Service Worker Cache                                   │
│      └─▶ Forward Proxy (ISP/Corporate)                      │
│          └─▶ CDN Edge (Cloudflare, Akamai)                  │
│              └─▶ Reverse Proxy (Nginx/Varnish)              │
│                  └─▶ Application Cache (Redis)              │
│                      └─▶ Database                           │
└─────────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Forward Proxy Cache (ISP/Corporate Layer)

Caches requests made by users behind a firewall.

The Trap: You have zero control here. If you don't use fingerprinted filenames, a corporate proxy might serve an old version of your React app for weeks.

Fix: Always use content-hashed filenames for static assets.

Reverse Proxy Cache (Gateway Layer)

Your Nginx/Varnish fleet sitting in front of application servers.

Micro-caching Pattern:

# Cache for just 1 second
proxy_cache_valid 200 1s;
Enter fullscreen mode Exit fullscreen mode

For viral real-time endpoints (trending news feed), this collapses 10,000 simultaneous requests into a single origin hit, protecting your backend.

CDN (Edge Caching)

Dynamic Content with ESI (Edge Side Includes)

Assemble pages where some parts are cached longer than others:

<!-- Header cached globally for 24 hours -->
<esi:include src="/fragments/header" />

<!-- User profile fetched dynamically per-request -->
<esi:include src="/fragments/user-profile" />

<!-- Footer cached globally for 24 hours -->
<esi:include src="/fragments/footer" />
Enter fullscreen mode Exit fullscreen mode

Surrogate Keys (Smart Purging)

Instead of purging URLs one by one, tag your assets:

Cache-Tag: product-123, category-electronics
Enter fullscreen mode Exit fullscreen mode

When the product price changes, send one "Purge by Tag" command to clear every related asset globally.


3. Application & Data Layers

Redis vs. Memcached

Feature Redis Memcached
Data Structures Lists, Sets, Hashes, Sorted Sets Key-Value only
Persistence Yes (RDB/AOF) No
Pub/Sub Yes No
Threading Single-threaded Multi-threaded
Use Case Complex state, real-time leaderboards High-throughput simple caching

When to use Redis:

  • Sorted Set for real-time leaderboard
  • Pub/Sub to invalidate local caches across 100 app servers
  • Session storage with TTL

When to use Memcached:

  • Pure object caching
  • Maximum throughput for simple key-value lookups

ElastiCache (AWS Managed)

Provides Redis/Memcached with:

  • Automatic sharding
  • High availability
  • Multi-AZ replication

4. Cache Consistency Patterns

Pattern How It Works Trade-off
Cache-Aside App checks cache first, fetches from DB on miss, writes to cache Simple but risk of stale data
Write-Through Write to cache AND DB simultaneously Consistent but slower writes
Write-Behind Write to cache immediately, flush to DB async Fast writes but risk of data loss
Read-Through Cache fetches from DB on miss automatically Simpler app code

Write-Behind Example (View Counters)

// Increment in Redis immediately (fast)
await redis.incr(`views:article:${id}`);

// Background job flushes to DB every 5 minutes
// Risk: Data loss if Redis fails before flush
Enter fullscreen mode Exit fullscreen mode

5. Special Case: Video Streaming (HLS/DASH)

Streaming requires a "binary-first" caching mindset.

Different TTLs for Different Files

File Type Purpose TTL
.m3u8 / .mpd (Manifest) "Map" of the stream 1-2 seconds
.ts / .m4s (Segments) Actual video chunks Long-term (immutable)

Why Manifests Need Short TTL

#EXTM3U
#EXT-X-TARGETDURATION:6
#EXTINF:6.0,
segment001.ts    ← Already cached at edge
segment002.ts    ← Already cached at edge
segment003.ts    ← NEW! User needs to see this
Enter fullscreen mode Exit fullscreen mode

If manifest is cached too long, users fall behind the live edge.

Low-Latency HLS (LL-HLS)

Uses Blocking Playlist Reload:

1. Client requests manifest
2. CDN sees next segment isn't ready yet
3. CDN HOLDS the request open (doesn't return 404)
4. When segment is ready, CDN returns updated manifest
Enter fullscreen mode Exit fullscreen mode

CDN Config Required: Must support "holding" requests, not immediately returning stale/404.


6. Quick Reference: Cache Headers

Header Purpose Example
Cache-Control Main caching directive max-age=3600, public
ETag Content fingerprint for validation "abc123"
Last-Modified Timestamp-based validation Wed, 21 Oct 2024 07:28:00 GMT
Vary Cache separately by header Vary: Accept-Encoding
Surrogate-Control CDN-specific directives max-age=86400
Cache-Tag For tag-based purging product-123

7. Interview Tip

"Caching is about trade-offs between freshness and speed. I use fingerprinted assets with immutable caching for static files, short TTLs with stale-while-revalidate for API data, and micro-caching at the reverse proxy to handle thundering herds. For complex invalidation, I use surrogate keys to purge by tag rather than URL. At the data layer, I choose Redis for complex structures and Pub/Sub invalidation, Memcached for pure throughput."

Top comments (0)