Yuvraj Raulji | Headless optimisation
Headless storefronts that disappoint almost always disappoint for the same three reasons: pages render per request that did not need to, GraphQL fetches far more than the template shows, and the JavaScript bundle grew every sprint without anyone owning the total. All three are recoverable, and none of them is an argument against the approach.
Direct answer
Usually because it renders more per request than it needs to. The three recurring causes are templates that render dynamically when they could be cached and revalidated on commerce events, GraphQL queries that fetch far more than the page displays because the boundary mirrors the platform schema, and a JavaScript bundle that grew with every feature while nobody owned the total. Server response and cache hit rate are where the recoverable time is; image and font work matters but arrives after the response, so it moves the smaller half of the number.
Best suited for
- A headless build that is slower than the theme it replaced
- Core Web Vitals failing in field data
- Cache hit rates nobody measures
- Bundle size that grew without a budget
What this page is not
This is work on a storefront that already exists. If the rendering model was never designed, the fix is structural rather than incremental, and tuning around it will not hold.
Headless architecture, when the rendering model is the problem
The problem
The symptom as the person carrying it would describe it, and the part that shows up in the numbers rather than in the ticket queue.
The headless build is slower than the theme it replaced
What it costs
The central promise of the project is visibly unmet, which puts every future front-end investment under suspicion. It is nearly always a rendering and caching decision rather than a framework limit.
Nobody measures the cache hit rate
What it costs
The team optimises what it can see, which is bundle size and images, while most of the latency sits in requests that missed the cache and were built from scratch.
GraphQL returns far more than the page renders
What it costs
Every request pays for fields nothing displays, on the storefront and on the commerce platform behind it. It is invisible in the browser and expensive at both ends.
The bundle grew every sprint
What it costs
No budget, no owner, and a date-formatting library shipped three times. Interaction latency degrades gradually enough that nobody can point at the release that caused it.
Approach
In this order, and the order is the opinion. Most of what goes wrong on this kind of engagement is a step taken before the one it depends on.
Measure the field, by template
Real user data segmented by template and device, alongside cache hit rate and server response. A single site-wide score hides which template is losing the money.
Move templates into the right rendering tier
Anything rendering per request that could be cached and revalidated on a commerce event gets moved. This is where most of the recoverable time is and it is usually a configuration decision rather than a rewrite.
Cut the query to the template
Query shape driven by what the page renders, not by the platform schema. Over-fetching is the standard headless performance failure and fixing it improves the storefront and the commerce backend at the same time.
Put a budget on the bundle
Route-level budgets enforced in the pipeline, duplicate libraries removed, and anything that can be server-rendered kept off the client. A budget nobody enforces is a preference.
Then images, fonts and stability
Sizing, format, preloading the LCP element and eliminating layout shift. Real, and it arrives after the response, so it belongs after the response work rather than before it.
Scope
Rendering
Tier review per templateRevalidation triggersEdge cachingCache hit rate measurement
Data
GraphQL query shapeOver-fetch eliminationRequest waterfall reductionPayload budgets
Client
Bundle budgetsDuplicate dependency removalHydration costThird-party script control
Experience
Core Web Vitals in the fieldLCP element handlingLayout stabilityFont and image pipeline
Proof
A headless storefront where the rendering and caching strategy, rather than the framework, decided the result.
Headless commerce · Fashion
Headless fashion storefront
High-performance headless commerce architecture for India’s fastest-growing men’s fashion brand.
HeadlessStorefront APIPerformance
Outcome
The storefront finally does what it was built for
When a decoupled front end underperforms the theme it replaced, the project has not delivered its central argument. Moving templates into the right rendering tier is usually what closes that gap, and it is rarely a rewrite.
A budget that outlives the engagement
Bundle budgets in the pipeline and cache hit rate on a dashboard are what stop the next six months of features quietly undoing this work. Performance without a guard rail is a one-off.
No Lighthouse score or percentage improvement is published here. Headless performance is a property of the rendering and caching decisions rather than of the approach, so a number from another storefront describes its architecture, not what is available in yours.
Questions
- Why is our headless storefront slower than the old theme?
- Almost always because too much renders per request. A cached page served from the edge beats a theme comfortably; a page rendered on demand against a slow GraphQL query does not. The fix is moving templates into a cached tier with invalidation driven by commerce events, and it is usually configuration rather than a rewrite.
- What should we measure on a headless storefront?
- Cache hit rate and server response first, then Core Web Vitals from field data segmented by template. Lab scores are useful for regression checks and poor for finding out where the money is going, because they do not tell you how often you missed the cache.
- How much does GraphQL over-fetching actually cost?
- More than it looks, because it is paid at both ends: the storefront waits longer and the commerce platform does more work per request. It is invisible in the browser, which is why it survives so long, and it is found by comparing what a query returns against what the template renders.
- Is bundle size still a problem with modern frameworks?
- Yes, mainly for interaction latency rather than initial paint. Server components and streaming reduce how much has to ship, but nothing prevents a team adding libraries every sprint. Route-level budgets enforced in the pipeline are what actually hold the line.
- Can this be fixed without rebuilding?
- Usually. Rendering tiers, query shape and bundle budgets are all changeable in place. The exception is a storefront with no coherent rendering model at all, where tuning around the structure does not hold and the fix is architectural.
Next step
Describe what is actually in front of you and we will work out whether this is the right piece of work before anyone scopes it. That conversation is usually shorter than people expect, and it occasionally ends with me saying you do not need the project.