How we hit 95+ Lighthouse scores on every site we ship
A 95+ Lighthouse score is not an achievement — it is a baseline. Here is the exact stack and decisions we use to hit it on every project we ship, whether it is a Shopify storefront, a WordPress build, or a custom React app.
Images do roughly 70% of the work. We default to AVIF with a WebP fallback, responsive `srcset` covering at least three breakpoints (640w, 1024w, 1536w), lazy loading below the fold, and explicit `width` and `height` attributes to prevent cumulative layout shift. The hero image gets `fetchpriority="high"` and a preload hint in the document head — this single change has moved LCP scores from the high 70s into the 90s on dozens of audits.
We never let designers ship raw exports from Figma. Every image goes through a pipeline that strips metadata, applies the right compression for the image type (lossy for photos, lossless for UI), and outputs the modern formats automatically. Sharp on the build side, the Image API on the runtime side. The bundle never sees a 2MB hero image.
Fonts are the second-biggest performance lever. We self-host all fonts, subset them to just the characters used (Latin only for English-only sites — this can cut font payload by 60%), and use `font-display: swap` so text renders immediately with a fallback. We also preload the two or three font weights actually used above the fold, and nothing else.
The other 30% is being ruthless about JavaScript. We defer everything not needed for first paint. We hydrate islands, not the whole page — server-render where we can, hydrate interactive widgets only when they enter the viewport. We avoid 'kitchen sink' UI libraries and instead pull single-purpose components that have no runtime dependencies.
Third-party scripts are the silent killer of Lighthouse scores. We audit every script that wants to be on the page: analytics, A/B testing, chat, pixels, heatmaps. Each one gets a budget and a justification. If it cannot be loaded with `defer` or after user interaction, it usually does not get on the site. A typical store we audit has 18 to 25 third-party scripts; we usually cut that to 6 to 10 without anyone noticing.
Edge caching is the secret weapon. We run static-first wherever possible — pre-render pages at build time, serve from a CDN, and revalidate on a schedule or on demand. For dynamic content (cart, account), we use stale-while-revalidate so the visible page is always instant and the fresh data slides in behind it. The user never waits.
Database queries deserve the same scrutiny as front-end assets. On Shopify and WordPress, we look for N+1 queries on collection and category pages, missing indexes on custom queries, and theme files that fetch metafields in a loop. A single fix here can shave 300 to 500ms off TTFB.
For Core Web Vitals specifically: LCP under 2.5s, INP under 200ms, CLS under 0.1. We measure on a throttled mobile profile because that is what real users experience. A site that scores 99 on desktop and 65 on mobile is failing — Google ranks on mobile.
Monitoring matters as much as building. We wire every site we ship to a real-user monitoring tool (we like SpeedCurve and the Vercel Speed Insights for our own stack) so we catch regressions before customers do. Performance is not a project, it is a discipline.
If you remember nothing else: optimize images, defer JavaScript, audit third-party scripts, and serve from the edge. Those four habits cover 95% of the gap between a slow site and a fast one. Everything else is finishing work.
Ready to apply this to your site?
Get a fixed-scope quote in under two minutes.