advanced 3 min answer

An e-commerce product page has cacheable content, a personalised recommendation strip, a logged-in header and a live stock indicator. What runs at the edge and where does each piece of state live?

edgecloudflarecachingpersonalisationstate
Show the full answer Hide the answer

What is being tested

Whether you can decompose a page by cacheability and state locality rather than treating it as one unit.

The decomposition

The product content — description, images, specifications. Fully cacheable, identical for everyone, changes rarely. Cache at the edge with a long TTL and invalidate on publish. This is the bulk of the bytes and it should never reach the origin.

The logged-in header — name, cart count. Small, per-user, cheap to compute. Two viable approaches: assemble at the edge from a signed token the user already carries (no origin call at all, which is the strongest option), or fetch client-side after the cached page renders. The token approach is better because it avoids a visible layout shift and an extra round trip.

Recommendations. Per-user, expensive, and — crucially — not required for the page to be useful. Fetch client-side, asynchronously, after render. If it fails, the page still sells the product. This is the clearest case of a component whose failure should be invisible.

Live stock indicator. Changes frequently, matters commercially, and being wrong has a real cost. Short TTL — seconds — with stale-while-revalidate, or a client-side fetch. Never cached long, and never trusted at checkout: the authoritative check happens at the point of commitment, which is the same search-is-eventually-consistent, commit-is-authoritative rule that governs every dynamic-inventory marketplace.

The general technique

Cache the page, punch holes for the personal parts. The alternative — treating the whole page as uncacheable because 5% of it is personalised — is the single most common and most expensive mistake in this area. It converts a workload the CDN could absorb entirely into full origin load.

Two mechanisms: edge-side assembly of cached fragments plus a small dynamic piece, or a cached shell that the client fills in. Both are fine; the edge assembly gives a better first render and the client-side approach is simpler.

Where the state lives

This is the question that decides the design, and the honest answer is that edge state is the hard part, not edge compute. Running code in 300 locations is easy; giving it consistent data is not. The available options:

State Where Why
Product catalogue Replicated to edge, eventually consistent Read-heavy, staleness tolerable
Session / identity In a signed token the client carries No lookup needed at all
Cart Origin or a single authoritative region per user Must be consistent; user-affine
Stock Origin, with a short-TTL edge cache Authoritative check at commit only
Experiment assignment Computed at edge from a hash of the user ID Deterministic, needs no storage

The underrated pattern is a single authoritative location per object, with edges routing to it. It gives strong consistency for that object and locality for the users who matter most for it — which fits carts, collaborative documents, game sessions and chat rooms well.

Failure scenarios to name

  • Caching a personalised response because the cache key omitted the user dimension. This leaks one user's data to another and is the highest-severity mistake available here.
  • Business logic drifting to the edge, so critical behaviour lives in a constrained runtime with limited debugging.
  • A configuration change deployed globally in seconds with no canary — the blast radius is every user at once.