Cates Works
All notes
Performance/ 7 min read

The kitchen and the menu: why fast and accurate stopped being a tradeoff

August 6, 2026

Walk into a restaurant and you’re seated in seconds, menu already in your hands. Nobody makes you wait at the door while the kitchen confirms what’s actually in stock tonight — you get the menu instantly, and the one thing that has to be live (do they actually have the halibut) gets checked and confirmed a moment later, at the table, without you ever noticing the gap. Most storefronts don’t work like that. They either hand you a menu that was printed last week — fast, but the halibut sold out Tuesday — or they make you stand at the door while someone runs to the kitchen to check everything before you’re allowed to sit down. Streaming the fast parts instantly and confirming the live ones a moment later, invisibly, is the architecture that finally builds the restaurant, not the printed menu or the doorway interrogation.

The choice that used to be unavoidable

Static pages are fast because they’re already built — pre-rendered once, served instantly from a CDN, no server round-trip standing between a click and a page. The catch is they’re frozen. The price on the page is whatever price it was at build time. If it changed an hour ago, the page is lying, quietly, to every visitor until the next rebuild.

Dynamic pages fix that by building the page fresh on every request — the price is always correct, because it’s fetched live. The catch is the visitor waits for that fetch before they see anything at all. Every product page becomes a small negotiation between honesty and patience, and the visitor pays for it in seconds.

Recap: static gets you speed and stale data, dynamic gets you correctness and a wait — and until recently, a storefront had to pick a side.

What ships today: streaming, not a prerendered shell

The unchanging parts of a product page — layout, photos, description, SEO tags — render fast, with nothing slow blocking them. The parts that have to be live — price, stock, cart contents, recommendations — stream in a fraction of a second later, filling in over a skeleton the visitor is already looking at. One request, one page, two speeds, working together instead of forcing a choice.

Worth saying plainly, because overselling this kind of thing is exactly the sort of thing a technical buyer catches: Next.js 16 does ship a `cacheComponents` flag that gets you a true prerendered-shell-plus-dynamic-holes architecture — but it’s a global, all-or-nothing setting, off by default, and turning it on means every route in the app has to comply, including the ones that genuinely need to stay fully dynamic. That’s a real constraint, not a footnote, so rather than flip a repo-wide flag to make one product page faster, this architecture gets the same effect a different way: the fast parts render immediately, the live parts stream in via Suspense in that same response, and correctness comes from cache-tag and webhook-driven revalidation instead of a prerendered cache. Different mechanism, same restaurant.

Recap: the shell renders fast and the live parts stream in around it via Suspense, kept correct with cache-tag and webhook-driven revalidation instead of a rebuild.

Why the milliseconds were never a vanity metric

This is the part that gets treated as a nice-to-have right up until someone runs the numbers. Amazon’s own internal testing — one of the most cited data points in web performance, going back to the mid-2000s and still holding up — found that every 100 milliseconds of added page load time cost them 1% in sales. Not 1% of a marketing metric. 1% of sales.

Akamai found something similarly blunt from the other direction: a 2-second delay in load time increased bounce rate by 103%. Not double the bounces from a page falling over — double the bounces from two seconds of waiting.

The most rigorous version of this comes from a joint Deloitte and Google study, “Milliseconds Make Millions,” which isolated speed as a variable across 37 real retail, travel, and lead-generation brands rather than relying on a single company’s anecdote. A 0.1-second improvement in mobile site speed lifted retail conversion rates by 8.4% and average order value by 9.2%; travel conversions rose 10.1%. A tenth of a second. Not a redesign, not a new feature — a tenth of a second.

I already wrote about the Core Web Vitals side of this in a post called “Speed is a feature” — Largest Contentful Paint, Interaction to Next Paint, Cumulative Layout Shift, and why Google rewards fast sites twice, once with visitors and once with ranking. I won’t re-explain those here; go read that one for the vitals themselves. This post is specifically about the architecture that lets a storefront actually hit them without sacrificing live data to do it.

None of this stays true on its own, either — the architecture gets you fast on launch day, but a regression that quietly adds 400ms to checkout six months later doesn’t send you a memo. That’s what the Monitoring & Reliability capability is for: uptime and performance monitoring that catches a slowdown while it’s a graph, not after it shows up as a dip in conversion nobody can explain.

Recap: this isn’t a developer’s aesthetic preference. It’s a line item — measured, repeated, and independently confirmed across dozens of real businesses.

The tradeoff nobody tells you about

Here’s the part most pitches for “fast static sites” leave out, because it’s inconvenient: a fully static page has nothing dynamic to vary. You can’t run an A/B test on it, personalize it by visitor, or roll out a promotional price to half your traffic — there’s no live surface to change. Full static buys you speed by giving up your ability to experiment.

And a fully dynamic page buys you that experimentation back — but the speed cost of getting there is exactly what funds the visitor’s patience to see the experiment in the first place. A personalization engine nobody waits around long enough to experience isn’t personalizing anything.

Streaming is the one approach where you don’t have to choose. The shell renders fast and instant. The dynamic holes — price, stock, recommendations, and yes, an experiment variant or a personalized banner — stream in via Suspense, the same mechanism that was already live for other reasons. You get to run the test without paying for it in bounce rate.

Recap: static costs you the ability to experiment, dynamic costs you the speed that makes an experiment worth running, and streaming the dynamic holes in via Suspense is what lets you keep both instead of picking a casualty.

What I actually recommend, and why

Backend matters less than most pitches make it sound once the shell is built right — but I can only vouch for what’s actually been built and proven, which today is Shopify, via Hydrogen, and Medusa. If you’re starting from scratch, here’s the honest recommendation, not a menu of equal options:

  • Shopify, for most builds. If you’re already on Shopify, or you want its ecosystem — apps, point of sale, fulfillment network — this is the path of least resistance, with first-class support and zero commerce-logic compromises. It’s the default for a reason: lowest risk, biggest ecosystem, nothing exotic required.
  • Medusa, if ownership matters more than convenience. Open-source, self-hostable, same storefront architecture end to end. This is the pick for teams who want to own their backend outright or who are watching a take-rate add up at scale and want out of it.
  • Something else, if you’re already committed elsewhere. The pattern above — a shell built once, a backend wired in as a plain adapter — isn’t Shopify- or Medusa-specific in principle, but those are the only two I’ve actually built and can vouch for today. Moving a platform like Saleor, BigCommerce, Shopware, or Salesforce Commerce Cloud onto this architecture is a real, discussable path, not a rebuild from scratch — it just means building and proving that adapter for the first time, not assuming a drop-in swap.
  • Recap: default to Shopify unless you have a specific reason not to, Medusa is that specific reason when ownership or cost-at-scale matters, and moving something else onto this architecture is a real, buildable path — not something I’m claiming already works turnkey today.

The takeaway

Fast and accurate stopped being a tradeoff the moment the shell and the live data stopped sharing one request. The milliseconds were always worth real money — Amazon, Akamai, and a 37-brand Deloitte/Google study all measured it independently — and now the architecture exists to stop paying for speed with correctness, or correctness with speed.

Capabilities this touches

Let’s talk

Have a project, or a product that could work harder?

Most projects begin with a short, no-pressure discovery call.