Core Web Vitals in 2025: what actually moves the needle
Google's metrics evolved. The same culprits keep showing up in audits: third-party scripts, unoptimized images, and layout instability from injected content.
When we audit production websites, the goal is simple: identify what actually impacts Core Web Vitals versus what developers obsess over unnecessarily. The pattern is remarkably consistent.
The pattern we keep seeing
| Metric | Common failure | Primary cause |
|---|---|---|
| LCP | Most failing sites | Unoptimized hero images |
| CLS | Half of failing sites | Injected third-party content |
| INP | Most failing sites | Long JavaScript tasks |
| TTFB | A minority of sites | Slow origin response |
LCP: it is almost always images
When LCP fails, the cause is almost always a hero image served without optimization.
What works:
- AVIF format: 30-50% smaller than WebP at equivalent quality
fetchpriority="high": On the LCP image only- Preload hints: For above-fold images
- Proper sizing: No oversized images scaled down with CSS
- CDN with HTTP/3: Reduces time-to-first-byte for the image itself
What does not help much:
- Lazy loading above-fold images (actively hurts)
- Over-engineered loading spinners
- Complex placeholder generation
CLS: the third-party script problem
The bulk of layout-shift problems we see come from third-party scripts injecting banners, chat widgets, or ads after initial render.
The fix: reserve space for every known injected element.
.cookie-banner { min-height: 60px; }
.chat-widget { aspect-ratio: 1 / 1; width: 60px; }If the script loads, it fills the reserved space. If it fails, the layout does not shift.
INP: the JavaScript tax
INP is the metric that catches the largest share of sites we audit. The common thread is main-thread saturation from analytics, A/B testing frameworks, and over-hydrated client trees.
Specific fixes that worked:
- Defer non-critical analytics: Send beacon requests after
requestIdleCallback - Split A/B test logic: Run assignment server-side, not client-side
- Hydration boundaries: Use React Server Components for static content
- Web Workers: Move heavy computation off the main thread
- Event delegation: Reduce individual event listener overhead
Moving an A/B testing framework from client-side to an edge worker is often enough to take INP from problematic to comfortably under threshold.
TTFB: the forgotten metric
TTFB fails less often than the other metrics, but when it is bad, everything downstream suffers.
The fix is usually geographic: move compute closer to users. Edge functions, regional databases, and CDN caching at the PoP level.
The audit checklist we use
Before any launch, we run:
- Lighthouse CI in CI/CD with 90+ thresholds
- WebPageTest from 3 continents on 4G
- Chrome UX Report comparison for origin-level data
- Real-user monitoring with 75th percentile targets
- Third-party script inventory with performance budgets
The bottom line
Most performance issues are not exotic. They are images, scripts, and layout shifts. Fix the basics before chasing micro-optimizations.