A one-second delay in page load time reduces conversions by ~7% and increases bounce rate measurably. In 2026, website speed is a product decision, an SEO signal, and a user experience requirement — not a nice-to-have. The good news is that 80% of the performance gains come from a small set of well-understood optimizations. Fix those first, then iterate.
What changed in 2026
- INP (Interaction to Next Paint) replaced FID as a Core Web Vitals metric. INP measures the latency of all interactions, not just the first — JavaScript-heavy apps need to care about this.
- AVIF is now widely supported. Chrome, Firefox, and Safari all support AVIF, which achieves ~50% smaller file sizes than WebP. Use it.
- HTTP/3 (QUIC) is default on most CDNs — if you're on a modern CDN, you get it automatically.
- LLM-generated content sites are competing on speed — if your pages feel slow compared to AI-generated alternatives, users leave.
The Core Web Vitals in 2026
| Metric |
What it measures |
Good threshold |
| LCP (Largest Contentful Paint) |
When the biggest visible element loads |
≤ 2.5 s |
| INP (Interaction to Next Paint) |
Worst interaction response time |
≤ 200 ms |
| CLS (Cumulative Layout Shift) |
Visual stability during load |
≤ 0.1 |
Measure with PageSpeed Insights (real-world data) and Lighthouse (lab data). Real-world data from the CrUX dataset is what Google uses for ranking.
1. Fix images first
Images account for ~50% of average page weight. Every image should be:
<!-- Use modern format, correct dimensions, lazy-load below fold -->
<img
src="hero.avif"
width="1200"
height="630"
alt="Hero image"
loading="eager"
fetchpriority="high"
/>
<!-- Below-the-fold images -->
<img src="feature.avif" width="600" height="400" alt="Feature" loading="lazy" />
- Convert to AVIF (or WebP as fallback) — use Squoosh, Sharp, or a build-step plugin.
- Set explicit
width and height to prevent CLS.
loading="lazy" for everything below the fold; fetchpriority="high" for your LCP image.
- Use responsive images with
srcset for different viewport sizes.
2. Optimize your JavaScript
JavaScript is the second biggest culprit. Audit your bundle with webpack-bundle-analyzer or Vite's rollup-plugin-visualizer.
# Vite build with bundle analysis
npx vite build --mode analyze
# Check your bundle size impact before adding a package
npx bundlephobia <package-name>
Key moves:
- Code-split by route — don't load the checkout page's JS on the homepage.
- Tree-shake — ensure your bundler eliminates unused code.
- Defer non-critical scripts — analytics, chat widgets, A/B testing libraries.
- Replace heavy libraries — replace Moment.js with
date-fns, Lodash full with specific imports, Chart.js with lightweight alternatives.
3. Use a CDN
For any site with global traffic, a CDN is not optional.
| Setup |
TTFB (typical) |
| Origin server only (US East) |
600–1200 ms (user in Asia) |
| CDN with edge caching |
30–80 ms (from nearest PoP) |
| CDN + HTTP/3 + early hints |
~20–50 ms |
Cloudflare (free tier is real), Fastly, and AWS CloudFront are the main options. At minimum, put your static assets and HTML pages behind a CDN.
4. Set correct cache headers
# Nginx example — fingerprinted assets can be cached forever
location ~* \.(js|css|avif|webp|woff2)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
# HTML: revalidate every time
location ~* \.html$ {
add_header Cache-Control "no-cache";
}
Content-addressed filenames (e.g., main.3f9a2b.js) let you set immutable cache headers safely — the filename changes when the content changes.
5. Reduce Time to First Byte (TTFB)
- Server-side rendering or static generation — don't make the browser wait for client-side JS to render the initial page.
- Edge functions for personalization — run lightweight logic at the CDN edge rather than round-tripping to an origin.
- Database query optimization — use indexes, avoid N+1 queries, add query result caching (Redis) for hot reads.
Common mistakes
Not setting a fetchpriority="high" on the LCP image. The browser can't know which image is the LCP candidate without the hint — add it.
Third-party scripts loading synchronously. A single <script src="..."> without async or defer blocks the parser. Audit your third parties.
Layout shifts from fonts. Use font-display: swap and preload critical fonts. Use size-adjust to prevent FOUT-induced CLS.
Over-optimizing before measuring. Run Lighthouse and PageSpeed Insights first. Fix the highest-impact findings, re-measure, then iterate.
Ignoring mobile. Google indexes mobile-first. Run your Lighthouse test in mobile mode.
What to skip
- Concatenating all CSS into one file — with HTTP/2+, parallel requests are cheap; over-concatenation hurts cache granularity.
- Inlining large scripts — inlined JS can't be cached; only inline critical CSS that's genuinely tiny (<2 KB).
- Preloading everything — only preload the LCP image and critical fonts; preloading everything negates the benefit.
FAQ
What Lighthouse score should I aim for?
90+ on Performance is the practical target. The difference between 90 and 100 often involves micro-optimizations with little real-user impact. Prioritize real-user metrics (CrUX) over lab scores.
Does website speed actually affect Google ranking?
Yes, directly via Core Web Vitals as a ranking signal. It also affects rankings indirectly through bounce rate and dwell time.
How do I measure real-user performance?
PageSpeed Insights shows field data from the Chrome User Experience Report (CrUX). For your own analytics, add the web-vitals JS library.
What is the fastest website stack in 2026?
Static HTML + CDN wins on pure speed. Astro, Next.js with static export, or plain HTML all deliver <1s LCP with correct optimization.
Where to go next