Cache strategies
In the SHOPin storefront accelerator, several caches stack on top of each other. They do not share invalidation—mixing them up leads to stale UI, wrong privacy boundaries, or extra load on the BFF and upstreams. This page is a layer map; headers and edge behavior are expanded under CDN configuration.
Further reading: NestJS caching, TanStack Query — caching examples.
Next.js Data Cache (server)
- Role — Caches
fetchresults during RSC / server rendering. - Use — Shared data with a freshness window (e.g. PLP/PDP, i18n):
fetch(..., { next: { revalidate, tags } }). - Invalidate —
revalidateTag/revalidatePathfromnext/cache, orrevalidateTTL. - Avoid — Per-user or private data:
noStore()orfetch(..., { cache: 'no-store' }). - Note — Independent of
Cache-Controlon the HTML response.
Next.js full route cache / HTML (HTTP)
- Role — Browser and CDN reuse of rendered HTML (and related route cache rules).
- Use — Pages where the same HTML is safe for many users (marketing, mostly static).
- Configure —
Cache-Controlvianext.config.tsheaders or middleware. - Avoid — Authenticated or personalised HTML:
no-store(or equivalent). - Note — Does not control the Data Cache; only HTTP caching of that response.
React Query (client)
- Role — Per-tab client cache (dedupe,
staleTime, refetch, optimistic updates). - Use — Client components: typical pattern is
useBffFetchClientinside the queryqueryFn; tunestaleTimeand refetch-on-focus as needed. - Invalidate —
queryClient.invalidateQueries({ queryKey: [...] })after mutations or when server state may have changed. - Avoid — Treating cached values as authoritative for totals, stock, pricing, or permissions without a fresh BFF read.
BFF HTTP cache (Cache-Control / ETag)
- Role — Browsers and CDNs cache JSON/API responses from Nest.
- Use — Public or shared responses; optional
ETag/Last-Modifiedfor conditional requests. - Configure — e.g.
Cache-Control: public, s-maxage=…,stale-while-revalidate=…where safe. - Avoid — Private or cookie-scoped endpoints:
no-store. - Note — Next’s server
fetchData Cache does not follow these headers for its own semantics.
NestJS in-process cache (CacheModule / interceptors)
- Role — Memory or Redis-backed cache inside the BFF.
- Use — Expensive upstream calls with keyable, safe responses.
- Invalidate — TTL and/or explicit key eviction (
@CacheKey, store APIs). - Ops — Multiple BFF instances need a shared store (e.g. Redis) or caches diverge per replica.
CDN / edge
- Role — Edge caching from response headers (
s-maxage,stale-while-revalidate,Vary). - Use — Public HTML and APIs in front of Next and/or the BFF.
- Note — Still separate from the Next.js Data Cache.
Static assets (public/, next/image, build chunks)
- Role — Long-lived hashed assets.
- Use — Images, fonts, JS/CSS chunks: usually immutable with long
max-age(e.g. one year).