Skip to content

Core Web Vitals in Production

Moving past lab scores: how to track LCP, INP, and CLS with real users, what usually breaks them, and fixes that hold up after launch.

  • performance
  • web vitals
  • monitoring
  • ux
  • frontend

A green Lighthouse score on your machine doesn’t mean users are having a good time. Core Web Vitals are field metrics. This is how I think about them once a site is live, as a follow-up to my post on frontend observability.

Lab vs field

Lab (Lighthouse, local profiling) is great for debugging and catching regressions in CI.

Field (CrUX, RUM) is what Chrome users experience on real devices and networks.

I ship with lab checks and judge success by field data. The two disagree more often than you’d expect, especially on pages heavy with images or third-party scripts.

The three metrics

LCP (Largest Contentful Paint) is usually the hero image, the headline block, or the main product visual. Slow LCP tends to come from oversized images, the hero being discovered late, fonts blocking render, or a slow TTFB.

INP (Interaction to Next Paint) measures how quickly the page responds to clicks and taps. Long main-thread tasks, heavy hydration, and expensive event handlers are the usual causes. INP replaced FID as the interactivity metric.

CLS (Cumulative Layout Shift) measures how much the page jumps around. Reserve space for images and embeds, don’t insert banners above existing content, and be careful with late-loading fonts and ads.

What breaks cultural and marketing sites

Patterns I see on Astro and other content sites:

  • Hero images without width and height, or without a proper srcset
  • Carousels and embeds that shift when they finally load
  • Cookie banners and announcement bars injected late
  • One more analytics or chat widget on the critical path

Static HTML gives you a head start. Third-party scripts can undo it in an afternoon.

Fixes that tend to stick

  1. Optimize and prioritize the actual LCP element, not every image on the page
  2. Self-host critical fonts with a sensible font-display
  3. Reserve space for media and dynamic slots
  4. Defer non-essential scripts and load chat or analytics after idle where possible
  5. Check field data after every release, not just before launch

Make it a habit

Add a lightweight RUM setup or rely on CrUX and Search Console. Tie regressions to releases. When INP spikes, profile the slow interaction instead of guessing with another round of CSS tweaks.

Observability and Web Vitals work best together. Watching both is how you fix what users notice rather than what an audit screenshot shows.

Back to blog