Core Web Vitals is a small set of metrics Google publishes to describe how a page feels to the person using it. There are three of them, and each one stands for a different complaint a real visitor might have.
- LCP — Largest Contentful Paint. How long until the biggest thing in the viewport is painted. Roughly: “when does the page look like it has arrived?”
- CLS — Cumulative Layout Shift. How much the content jumps around after it appears. Roughly: “does the page move under my thumb while I read it?”
- INP — Interaction to Next Paint. How long the page takes to visibly respond to taps, clicks and key presses. Roughly: “does it feel dead when I touch it?”
The thresholds
These are Google’s published thresholds. A page is “good” if it is at or under the first number, “needs improvement” up to the second, and “poor” above it.
| Metric | Good | Poor above |
|---|---|---|
| LCP | 2.5 s | 4 s |
| CLS | 0.1 | 0.25 |
| INP | 200 ms | 500 ms |
Two details matter more than the numbers themselves. First, the assessment is made at the 75th percentile of page loads — so “good LCP” means three quarters of your visits were at or under 2.5 s, not that your average was. The slowest quarter of your audience is exactly the quarter the metric is designed to notice. Second, a URL passes Core Web Vitals only when all three metrics are good at that percentile.
Lab data and field data are two different things
This is where most of the confusion lives, so it is worth being precise about which tool produces which.
Lab data is a single scripted load on a machine you control, under simulated conditions. That is what Lighthouse does, what the Performance panel in Chrome DevTools does, and what the top half of a PageSpeed Insights report shows. It is reproducible, it is available before you have any traffic, and it can point at the specific resource that caused the problem.
Field data is what actually happened to real Chrome users on your site. That is the Chrome UX Report — CrUX — and it is what powers the bottom half of a PageSpeed Insights report and the Core Web Vitals report in Search Console. It is collected from Chrome users who have opted in to reporting, aggregated over a rolling 28-day window, and reported at the 75th percentile.
Google’s search ranking signal uses the field data. Your Lighthouse score is not the thing being measured.
Why the two disagree
None of these are bugs. They are consequences of the two datasets measuring different things.
Different hardware and network. Lighthouse’s mobile preset simulates a mid-range Android on a throttled connection. Your real audience is a distribution — cheap phones on congested mobile networks at one end, desktops on fibre at the other. Neither the good end nor the bad end of that distribution looks like the one simulated device.
Different moment in time. A Lighthouse run is right now. CrUX is a 28-day rolling average, so a fix you shipped last week is diluted by three weeks of the old page and will keep improving for a month after you stopped working. Do not judge a deploy by field data the next morning.
Different entry points. Lighthouse loads the URL cold, with an empty cache, as a fresh navigation. Real visits include repeat visitors with warm caches, and they arrive from links, from search, from your own internal navigation. A page that is fast on a warm cache and slow cold will look better in the field than in the lab; a page whose slowness is server-side will look bad in both.
CLS and INP need a session, not a load. Both accumulate across the life of a page visit. A scripted load that stops after a few seconds and never scrolls or taps cannot see the shift caused by a lazy-loaded ad below the fold, and cannot see a slow interaction because nobody interacted. This is the big one: Lighthouse does not measure INP at all. It reports Total Blocking Time as a lab proxy for responsiveness. TBT is a useful proxy — main-thread work is the usual cause of both — but it is not the same metric, and a 0 ms TBT does not guarantee a good INP in the field.
Aggregation is per-origin when data is thin. CrUX only reports a URL when that URL has enough samples. Below that, PageSpeed Insights falls back to origin-level field data, so you may be looking at your whole site’s numbers while believing you are looking at one page’s.
How to use both without going in circles
Field data tells you whether you have a problem, and for whom. Lab data tells you what the problem is, reproducibly, in a form you can attach a fix to.
So: start in Search Console or the CrUX section of PageSpeed Insights and find which metric fails at the 75th percentile, on which form factor. Then reproduce it in the lab under conditions that resemble the failing segment — mobile preset, throttling on, cache disabled. Fix it there, where you get a fast feedback loop. Then wait out the 28-day window and confirm in the field.
If a lab run refuses to reproduce a field failure, that itself is information. It usually means the cause is something a scripted cold load does not encounter: third-party scripts that only fire for real users, an interaction nobody performed, content below the fold, or a slow origin under real traffic that is fast when only you are asking.
My public case study quotes lab numbers, deliberately labelled as such — protectorguardrail.com. A lab number is a claim you can re-run, which is why it is the honest thing to publish. It is not a promise about what every visitor experienced, and I would not present it as one.