All articles
Performance

How to Get 90+ on PageSpeed Insights: The Headless Stack Playbook

·6 min read

Most Shopify stores Lighthouse-score around 70 on mobile. Most WooCommerce stores sit closer to 55. Headless storefronts on Next.js + Medusa.js routinely hit 90–98. That's not a tuning gap — it's a structural one. This article unpacks the structure and gives you the specific techniques to land 90+ on your own build.

The numbers below come from a tuned Next.js + Payload baseline (the stack I deploy from), not from staging environments or best-case demos.

Why PageSpeed matters in money

Before the techniques, the business case. Three numbers worth memorising:

  • Conversion drops ~1% per 100ms of added page load time (Amazon's classic finding, replicated many times since).
  • Mobile bounce rate jumps from 32% to 90% as load time goes from 1s to 5s (Google's own data).
  • Core Web Vitals are now a Google ranking factor — fast pages outrank slow pages on the same content.

For a store doing €100k/year, lifting conversion from 1.8% to 2.0% (a typical speed-driven gain) is €11,000/year in recovered revenue. That's why this isn't a vanity metric.

For a wider business-case comparison see the platform comparison →.

Why Shopify and WooCommerce cap out below 90

Both platforms hit a ceiling because of their architecture, not their config:

Shopify renders pages server-side from Liquid templates with a fixed runtime that includes the theme JS bundle, the app sandbox (every installed app injects scripts), and Shopify's own analytics. You can prune the theme, but you cannot remove the platform layer. Lighthouse 75–80 is the realistic ceiling.

WooCommerce renders pages from PHP via WordPress, with the theme JS, jQuery, and every active plugin's assets. Caching plugins (WP Rocket, LiteSpeed Cache) help — they get you from 40 to ~60–70. Past that, you'd need to strip core functionality, which kills the admin.

Both architectures fight the goal. Headless gets there because the architecture aligns with the goal.

The headless advantage in five mechanisms

A Next.js + Medusa.js storefront ships pages fast because:

1. Static or ISR pages. Product pages are pre-rendered at build time or cached at the edge after first request. The customer's browser receives a fully formed HTML page from a CDN, not a database-backed PHP/Liquid render.

2. The commerce engine is off the critical path. Medusa serves cart, checkout, and admin via API. The storefront calls those endpoints only when the customer interacts — never on initial page load.

3. No theme runtime. There's no jQuery, no Liquid renderer, no admin chrome. The storefront ships only the React it needs.

4. Granular JS bundles. Next.js code-splits per route. The homepage loads only homepage JS. The product page loads only product-page JS. Compare this to Shopify themes that ship the whole site's JS on every page.

5. Image pipeline is engineered, not bolted on. Next/Image converts to AVIF/WebP, sizes responsively, and lazy-loads below-the-fold. Cloudflare R2 serves from edge. This single thing accounts for 10–15 Lighthouse points on image-heavy stores.

The eight techniques that land 90+

Here's the specific checklist:

1. Static or ISR everything that's not personalised. Product listings, product pages, category pages, content pages — all pre-rendered or edge-cached. Only cart and checkout are dynamic.

2. Strict JS budget per page. Set a page-level limit (under 150kb gzipped for the storefront's own JS). Audit weekly with next build analyzer.

3. Defer or remove third-party scripts. Meta Pixel, Google Tag Manager, chat widgets — none of them belong in the critical render path. Move them to server-side tracking for Pixel and GA4. Here's the full guide →

4. AVIF/WebP via Next/Image, with explicit width/height. No CLS, no oversized images. For a 1200px product photo you'll ship ~30kb instead of the 300kb a CMS upload would give you.

5. Font subsetting + `font-display: swap`. Self-host fonts, subset to the characters you actually use, and never let invisible-text-during-font-load (FOIT) happen.

6. Preload only the LCP image and primary font. Anything else preloaded competes with the resource that actually paints.

7. Edge caching via your CDN. Cloudflare or Vercel edge cache for static assets and ISR pages. TTFB drops from 0.6s to 0.05s for cached responses.

8. Strip the analytics bloat. Many stores ship 12+ analytics tags. Audit, consolidate, and move the non-marketing-critical ones server-side.

What 96/100 actually looks like

For a tuned product page on the Next.js + Medusa baseline:

MetricValue
Performance score (mobile)96
LCP1.1s
CLS0.00
INP120ms
TTFB0.6s (cached) / 0.9s (first hit)
Total page weight380kb
JS shipped95kb gzipped

That's from a baseline build with real product photos, multilingual SEO metadata, schema markup, and analytics running — not a staging demo. Compare to the typical Shopify product page at ~1.4MB total weight and 350kb JS.

How to get there from where you are

If you're on a slow Shopify or WooCommerce store today, you have two real options:

  1. Tune what you have. Caching, image optimisation, app pruning, theme audit. Realistic gain: +15 to +25 Lighthouse points. You'll cap out around 75 on Shopify, 70 on WooCommerce.
  2. Move the storefront to headless. Keep your back-office where it is (or migrate that too) and rebuild the customer-facing storefront on Next.js. Realistic gain: +30 to +50 Lighthouse points, and you don't hit a ceiling. This is what the migration service → does.

Option 1 is cheaper. Option 2 stops being optional once the cost of slow pages exceeds the cost of building once correctly.

FAQ

Why do I need 90+ specifically? Isn't 75 fine? 75 is enough to not be penalised by Google's Core Web Vitals threshold. But the conversion-rate curve keeps climbing past 75 — every 100ms of improvement keeps converting more customers. There's no point at which faster stops being better.

Will switching themes get me to 90 on Shopify? A premium fast theme can lift Shopify scores by 10–15 points. Past the high 70s, you're fighting the platform's runtime. The structural ceiling exists no matter how good the theme.

How long does it take to build a 90+ store from scratch? A baseline online-store build takes 3–4 weeks and ships at 90+ out of the box. The performance work is part of the foundation, not a separate tuning pass.

Does headless help on Shopify (Hydrogen)? Yes — Hydrogen storefronts also hit 90+. The performance argument is settled there. The remaining argument with Shopify is cost and lock-in, covered in the Shopify hidden-costs piece →.

Next steps

If you want a fast store, the build starts at €2,000 and ships at Lighthouse 90+ as part of the baseline — not a paid add-on. See /services/online-store for what's included, or /services/custom-development for bespoke builds where speed is critical to the use case (booking, B2B, content-heavy storefronts).

Got a question on this?

Talk to me directly

Specific build, pricing, migration timing — anything that wasn't covered above, I answer personally within a working day.

Fill the brief