ESC

Type to search the knowledge base.

Frontend Caching Strategies

System design for frontend caching — HTTP, CDN, Service Worker, memory stores, and invalidation tradeoffs.

intermediate4 min read
  • system-design
  • interview
  • architecture
  • caching

Scope the problem

Caching is layered. Interviews fail when candidates only say “use Redis” for a frontend question. Cover what is cached, where, and how it invalidates.

In scope: static assets, API data on client, HTML documents, SW, memory caches.

The layers

┌────────────────────────────────────────────┐
│ In-memory (React Query / store)            │
├────────────────────────────────────────────┤
│ Service Worker Cache Storage               │
├────────────────────────────────────────────┤
│ HTTP browser cache                         │
├────────────────────────────────────────────┤
│ CDN / edge cache                           │
├────────────────────────────────────────────┤
│ Origin                                     │
└────────────────────────────────────────────┘

Each layer has different keys, TTLs, and privacy.

Static assets (JS/CSS/images)

Strategy Header idea
Fingerprinted bundles Cache-Control: public, max-age=31536000, immutable
HTML entry no-cache or short + revalidate
Images via CDN long cache + versioned URL or query hash

Never long-cache app.js without hash — users stick on broken deploys.

See caching static assets.

HTML documents

App type HTML caching
Marketing SSG long + CDN ISR
Personalized app shell private, no-store or short
Hybrid cache shell; client fetch user data

API data (client memory)

React Query / SWR patterns:

staleTime: 60_000,  // serve memory without refetch
gcTime: 5 * 60_000,
// invalidateQueries on mutation
Pattern Behavior
cache-first instant UX; risk stale
network-first fresher; slower
stale-while-revalidate best default for many GETs

Keys must include tenant, user, and params (multi-tenant).

Service Worker strategies

Resource Strategy
App shell cache-first
API GET list network-first or SWR
POST/PUT network-only + outbox offline
Images cache-first with limit LRU

Precache only shell; runtime cache carefully with versioned cache names (app-shell-v3).

CDN / edge

  • s-maxage for shared caches
  • stale-while-revalidate / stale-if-error
  • Purge on publish (tag-based purge ideal)
  • Respect Authorization — don’t cache personalized responses publicly

Invalidation map

Change How users see it
New frontend deploy new hashed assets; HTML revalidated
CMS content publish purge tag / ISR revalidate
User mutates entity client invalidateQueries; optional SW message
Feature flag kill short TTL flags bootstrap

Hardest: HTML + API + SW all holding different generations — design release so HTML points only to new asset hashes (atomic deploy).

Correctness hazards

  1. Caching authenticated responses on shared CDN
  2. SW serving old API schema after backend deploy
  3. Memory cache without tenant id
  4. max-age on HTML with inline config that must be fresh

Performance vs freshness matrix

Data Freshness need Cache
Logo low long CDN
Product PDP medium ISR minutes
Stock count high short / on-demand
Chat messages realtime memory + WS

Observability

  • CDN hit ratio
  • Client cache hit (custom)
  • Stale content complaints → correlate with TTL

Tradeoffs

  1. Aggressive SW vs confusing updates (need update UX)
  2. Long staleTime vs multi-tab inconsistency — broadcast invalidation
  3. Edge personalization vs hit ratio (edge rendering)

Interview close

Walk layers top-down for a specific product (e.g. news site): hashed assets immutable, HTML ISR, article JSON SWR in client, SW shell offline. State invalidation on publish and on user mutation. Call out auth cache dangers.

End-to-end example: product page

Resource Cache
/products/sku HTML CDN ISR 60s + SWR
product-abc.js immutable year
GET /api/product/sku browser memory 30s; CDN optional short
Review widget JS immutable; load deferred
User-specific price private, no-store

Debugging stale UI

  1. Check HTML generation time header
  2. Check SW cache name / version
  3. Check React Query devtools freshness
  4. Hard reload vs normal reload differences

Teach support a “disable SW” snippet for triage.

Interview close add-on

Emphasize auth + CDN as the #1 footgun and hashed assets + short HTML as the #1 default win.

Further reading