Front-End Engineering · Data Layer

Caching Strategies on the Client

Pick a strategy, then fire a read and watch the request move between the component, the client cache and the origin. Toggle the network, age the cache past its staleTime, or change the server data to see how each strategy trades freshness against speed and offline resilience.

REQUEST FLOW
press “Fetch data”
React / UI
Component
useQuery() · fetch()
Client
Cache
read / write
memory (query)~1ms
IndexedDB~12ms
SW Cache API~8ms
empty
Origin
CDN → Server
network
server: v1
Idle — no request yet
Choose a strategy above and press Fetch.
↻ revalidating in background…
EVENT LOGt = 0 ms
No events yet.
Network
staleTime
30 s
State
cache entryempty
cache age—
server versionv1
Actions
Strategy comparison
StrategyFirst byteFreshnessOfflineNetwork costBest for
Where these live in real APIs

HTTP Cache-Control

browser disk cache · CDN · the layer under everything
max-age=600fresh window before revalidation
stale-while-revalidate=30serve stale, refetch in background
no-cachestore, but revalidate every time (ETag → 304)
no-storenever cache (network-only)

Validators ETag / If-None-Match turn a miss into a cheap 304 Not Modified instead of a full payload.

TanStack Query / SWR

in-memory query cache · the default for React data
staleTimehow long data counts as fresh (no refetch)
gcTimehow long unused data lingers before eviction
refetchOnWindowFocusbackground revalidate on focus

Default behaviour is stale-while-revalidate: instant cached render, then a background refetch. SWR is named for exactly this pattern.

Apollo Client fetchPolicy

normalized GraphQL cache
cache-firstdefault · this playground’s Cache-First
cache-and-network≈ stale-while-revalidate
network-onlyalways fetch, still writes cache
no-cachefetch, never persist
cache-onlynever touch the network

Workbox (Service Worker)

Cache Storage API · powers offline / PWAs
CacheFirststatic, versioned assets
NetworkFirstAPI data that must be current
StaleWhileRevalidateavatars, non-critical data
NetworkOnly / CacheOnlyedge cases & precache

Persistence layers

what survives a reload, and how fast
Memoryfastest · lost on reload/navigation
Cache StorageRequest/Response pairs · SW-controlled
IndexedDBlarge structured data · async
localStoragetiny, sync, strings only — avoid for hot data

Invalidation & updates

the hard part of caching
invalidateQueriesmark stale → triggers refetch
optimistic updatewrite cache now, reconcile on response
prefetchwarm the cache before the user asks

“There are only two hard things… cache invalidation and naming things.” Time-based staleTime + event-based invalidation usually beats either alone.

interactive model · latencies are illustrative · serve from cache vs origin depending on strategy, freshness and connectivity