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.
| Strategy | First byte | Freshness | Offline | Network cost | Best for |
|---|
Cache-Controlmax-age=600fresh window before revalidationstale-while-revalidate=30serve stale, refetch in backgroundno-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.
staleTimehow long data counts as fresh (no refetch)gcTimehow long unused data lingers before evictionrefetchOnWindowFocusbackground revalidate on focusDefault behaviour is stale-while-revalidate: instant cached render, then a background refetch. SWR is named for exactly this pattern.
fetchPolicycache-firstdefault · this playground’s Cache-Firstcache-and-network≈ stale-while-revalidatenetwork-onlyalways fetch, still writes cacheno-cachefetch, never persistcache-onlynever touch the networkCacheFirststatic, versioned assetsNetworkFirstAPI data that must be currentStaleWhileRevalidateavatars, non-critical dataNetworkOnly / CacheOnlyedge cases & precacheMemoryfastest · lost on reload/navigationCache StorageRequest/Response pairs · SW-controlledIndexedDBlarge structured data · asynclocalStoragetiny, sync, strings only — avoid for hot datainvalidateQueriesmark stale → triggers refetchoptimistic updatewrite cache now, reconcile on responseprefetchwarm 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.