Retail & E-commerce// definition

Four caches sit between your product page and the shopper

In short

A commerce page passes through 4 caches: your own build or render output, the edge, the shopper's browser, and the in-page client store. You can purge the first 2 on demand. You can only expire the other 2, and only for the next request — which is why field placement, not TTL tuning, is the decision every later caching bug traces back to.

Key takeaways

  • 4 caches, 2 owners: build output and the edge are purgeable; the browser and the in-page store are only expirable.
  • Place fields by how wrong they are allowed to be, not by how expensive they are to fetch.
  • s-maxage and max-age are separate dials, so an edge copy can live for hours while the browser copy lives for seconds.
  • Imagery is never purged. Change the URL — a content hash makes an image permanently cacheable at every layer.
  • A field with no named purge path is not cacheable. Write the path down before the TTL.

Between the moment a price changes in your back office and the moment a shopper sees it, the value passes through 4 caches: your build or render output, the edge or CDN, the shopper's browser, and the in-page client store your JavaScript keeps while they browse. Each is invalidated by a different mechanism, and only the first 2 answer to you at all.

That asymmetry is the whole design rule. Build output and the edge can be purged in seconds when something changes. The browser cache and the client store cannot be reached — they expire on a timer you set earlier, and the only correction available is the next request. A field whose wrongness a shopper would notice within a minute therefore cannot carry a long browser lifetime, however cheap that would be.

The four layers, by who can clear them

LayerWhat it holdsWho clears itHow fast a fix lands
Build or render outputPre-rendered pages, framework data caches, generated feedsYou, by rebuild or targeted revalidationSeconds to minutes, depending on the rebuild unit
Edge / CDNWhole responses, keyed on URL and any headers you vary onYou, by purge or tag invalidationSeconds, globally, if your tags are right
Browser HTTP cacheWhatever you sent a max-age for, per deviceNobody. It expiresOnly on the shopper's next request after expiry
In-page client storeQuery results and state held while the tab is openYour own code, on refetch or navigationImmediately, but only in that tab
Each cache, its owner, and how fast a correction actually lands

Two directives keep the third layer honest and are worth naming because teams routinely set only one. A shared cache obeys s-maxage where a browser obeys max-age, so a single response can sit at the edge for an hour and in the browser for 30 seconds. stale-while-revalidate then lets the edge keep serving the old copy while it fetches a new one, which is how you get cache-hit latency on a field that still moves.

Field placement, which is the actual decision

Do not cache a page. Cache fields, and decide each one by how wrong it is allowed to be rather than by how expensive it is to fetch. A product page is a composite of things with wildly different tolerances, and treating it as a single cacheable unit is what forces the choice between a fast page and a truthful one.

FieldLongest safe lifeWhere it may liveCorrection path
Title, description, care and spec copyHours to daysAll 4 layersPurge on publish; drift here is cosmetic
ImageryEffectively permanentAll 4 layersNever purge — change the URL with a content hash
List priceMinutes at the edge, seconds in the browserBuild output and edge, short browser lifePurge on price change, and reprice at cart
Availability badgeSeconds, or not cached at allEdge with a very short life, or client fetchRefetch rather than purge
Variant-level stock countsNot cacheable in a shared cacheClient store only, refetched on variant changeRefetch on interaction
Personalised or contract priceNever in a shared cacheClient store, or a response marked privateNot cached publicly at all
Cart contents and countNeverClient store and the cart endpointRefetch on mount and on focus
Structured data and agent-readable feedsSame life as the field it describesBuild output and edgeRegenerate on publish
Where each field belongs, and how it gets corrected

What changes depending on how the storefront is built

The 4 layers exist in every architecture; what changes is how many of them you control. A themed storefront on a hosted platform owns the first 2 on your behalf, which removes a large class of decisions and a large class of levers at the same time — the honest version of that trade is headless or themed: what genuinely changes. A custom build inherits all 4 and the responsibility that comes with them.

Rendering strategy decides which fields can reach the first 2 layers at all, because anything rendered on the client is invisible to the edge and to any crawler that does not execute scripts. That is the trade laid out in what belongs on the server and what has to stay on the client. Imagery is the field where cache placement and page speed meet most directly — a content-hashed URL is permanently cacheable, but only if the browser can discover it early, which is the whole of why the hero image arrives last on mobile.

You can purge 2 of the 4 caches. The other 2 you can only apologise to, one request later.

The reader who is not a browser

Feeds and machine-readable documents live in the same 4 layers and are usually given no purge path at all, because nobody sees them go stale. An agent or comparison surface reading a cached feed will answer with yesterday's price long after your site is correct, and the answer it gives is not on a page you can fix — see the manifest an agent reads before anything else. Give generated documents the same invalidation event as the field they describe.

Caching decisions are also operational rather than purely technical: somebody has to be able to purge a collection during a trading day without a deploy, and that button is internal tools and ops work. This page defines the layers that the caching diagnostics elsewhere in storefront architecture and platform choice point back to, within software for retail and ecommerce.

Frequently asked questions

Short answers to the follow-ups this page tends to raise.

Which cache is responsible when a product page shows an old price?

Determine it by request, not by argument: fetch the page with caching disabled, then from the edge, then from a browser that has visited before. The first response that carries the old value names the layer. Doing this in order takes 2 minutes and prevents the usual outcome, which is purging the CDN repeatedly while a browser max-age of an hour keeps serving the old page.

Can availability be cached at all?

Only for seconds, and often it should not be. A stock badge is the field with the shortest tolerance on the page, because a shopper who sees in-stock and then cannot buy blames the store rather than the cache. The usual answer is to render the page from cache and fetch availability client-side, so the expensive part stays shareable and the volatile part stays fresh.

Should we cache the whole page or individual fields?

Cache the page, but only the parts of it whose tolerance matches. A product page splits naturally into a long-lived shell — copy, imagery, structure — and a short-lived set of commercial fields, and the architecture that survives is the one that lets those two be invalidated separately. A single cache unit for the whole page forces the shortest tolerance on everything.

How do we handle a price change during a promotion without a full rebuild?

Use tag-based invalidation rather than a rebuild. Tag every cached response with the product and collection ids it depends on, then purge by tag when the price changes, so 1 product update clears the 6 pages that referenced it instead of the whole site. Set this up before the promotion, because the alternative under load is a rebuild queue that lands after the trading hour it was meant to fix.

  • caching
  • storefront architecture
  • CDN
  • performance
// shipped work

The work behind this page

Builds from our portfolio that this page draws on.

Working on something in this space?

Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.

Start the conversation