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
| Layer | What it holds | Who clears it | How fast a fix lands |
|---|---|---|---|
| Build or render output | Pre-rendered pages, framework data caches, generated feeds | You, by rebuild or targeted revalidation | Seconds to minutes, depending on the rebuild unit |
| Edge / CDN | Whole responses, keyed on URL and any headers you vary on | You, by purge or tag invalidation | Seconds, globally, if your tags are right |
| Browser HTTP cache | Whatever you sent a max-age for, per device | Nobody. It expires | Only on the shopper's next request after expiry |
| In-page client store | Query results and state held while the tab is open | Your own code, on refetch or navigation | Immediately, but only in that tab |
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.
| Field | Longest safe life | Where it may live | Correction path |
|---|---|---|---|
| Title, description, care and spec copy | Hours to days | All 4 layers | Purge on publish; drift here is cosmetic |
| Imagery | Effectively permanent | All 4 layers | Never purge — change the URL with a content hash |
| List price | Minutes at the edge, seconds in the browser | Build output and edge, short browser life | Purge on price change, and reprice at cart |
| Availability badge | Seconds, or not cached at all | Edge with a very short life, or client fetch | Refetch rather than purge |
| Variant-level stock counts | Not cacheable in a shared cache | Client store only, refetched on variant change | Refetch on interaction |
| Personalised or contract price | Never in a shared cache | Client store, or a response marked private | Not cached publicly at all |
| Cart contents and count | Never | Client store and the cart endpoint | Refetch on mount and on focus |
| Structured data and agent-readable feeds | Same life as the field it describes | Build output and edge | Regenerate on publish |
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
The work behind this page
Builds from our portfolio that this page draws on.
AI Lease Management
AI-powered commercial real estate lease management for multi-brand operators — automates lease data extraction, obligation tracking, and portfolio intelligence.
Real EstateShortList
An AI recruiting screener that reads every application, scores candidates against the role, and hands recruiters a ranked shortlist with outreach already drafted.
HR & RecruitingRead next
- The cart token: the one object a storefront can never serve from cacheThe cart token carries identity, not contents. Once you see it that way, cached cart fragments and merge rules that silently discard items stop being surprises.definition
- Your product page's largest element arrives last on mobileHalf the time the largest element on a product page is not the product shot at all. Identify it first, then the fix is either an image-pipeline change or a script-order change.diagnostic
- The public storefront token: what a shopper-side key can readA storefront credential is safe because of its scope, not its secrecy. It ships to the browser by design — so the only question that matters is what it can return.definition
Related across the site
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