Perfect Lighthouse Score, Failing Core Web Vitals: Field Data vs Lab Data Explained
Why a 100/100 Lighthouse score coexists with a failing Core Web Vitals assessment, what CrUX actually measures, and how to debug the metric Google really uses.
Priya Raman
Principal Engineer, Crawl Systems · Published
The most common performance ticket we see reads: *"Lighthouse says 100. Search Console says we fail Core Web Vitals. Which one is lying?"*
Neither. They measure different things, and only one of them affects ranking.
1. Two Fundamentally Different Measurements
**Lab data** is a single synthetic load: one device profile, one throttled network, no extensions, empty cache, and — critically — **no user**. That is Lighthouse and the lower section of PageSpeed Insights.
**Field data** is the Chrome User Experience Report (CrUX): real loads by real Chrome users who opted into reporting, aggregated over a **28-day rolling window**, reported at the **75th percentile**.
Google uses field data for ranking. Lighthouse is a debugging tool, not a scorecard.
| | Lab (Lighthouse) | Field (CrUX) | | :--- | :--- | :--- | | Sample | 1 synthetic load | Thousands of real sessions | | Window | Right now | Trailing 28 days | | Statistic | Single value | 75th percentile | | Affects ranking | No | Yes | | Can measure INP | Only approximated | Yes |
2. The Three Reasons the Numbers Disagree
**The 75th percentile is not the average.** One in four of your users has a worse experience than your reported number. If your median device is a recent iPhone and your long tail is mid-range Android on 4G, the p75 lives in a different universe from your test machine.
**Lighthouse cannot measure INP.** Interaction to Next Paint requires an actual interaction. A synthetic load nobody clicks produces no INP at all, so Lighthouse substitutes Total Blocking Time as a proxy. TBT and INP correlate loosely and diverge exactly where it matters: a page with low TBT can still have terrible INP if one specific handler is slow.
**The 28-day window means you are looking at the past.** Ship a fix today and field data will not fully reflect it for four weeks. Teams routinely conclude a fix "did not work" eleven days in, revert it, and lose the improvement.
3. Reading Field Data Properly
In PageSpeed Insights, the top block is field data and the section below it is lab. Only the top block matters for ranking. If it says "not enough data", your URL lacks sufficient CrUX traffic and Google falls back to an **origin-level** assessment — meaning your slowest templates drag down pages that are individually fine.
In Search Console, the **Core Web Vitals** report groups URLs by similarity. Fix one URL in a group and the whole group typically moves, because the group shares a template.
The most useful signal is the distribution, not the headline number:
LCP good 62% | needs improvement 21% | poor 17%
Passing requires 75% in "good". At 62% you are not far off, and the 17% poor bucket is usually one template or one device class, not the whole site.
4. Collect Your Own Field Data
CrUX is limited to Chrome users, aggregated, and delayed. You can measure your own users directly, in real time, with no such constraints:
import { onINP, onLCP, onCLS } from "web-vitals";const report = (metric: { name: string; value: number; rating: string }) => { navigator.sendBeacon("/api/vitals", JSON.stringify(metric)); };
onLCP(report); onINP(report); onCLS(report); ```
`sendBeacon` survives page unload, which is exactly when these metrics finalise. This gives you per-route, per-device breakdowns the day you ship, rather than four weeks later.
5. The Debugging Order That Works
1. **Start in the field.** Identify the failing metric and the failing template from CrUX or your own RUM data. 2. **Reproduce in the lab, on the right profile.** Set Lighthouse to mobile with 4x CPU throttling. A desktop test on a workstation reproduces nothing. 3. **Fix the cause, not the score.** For LCP, the cause is usually a late-discovered image or a render-blocking font. For INP, it is a long task on a specific handler. For CLS, it is an element without reserved dimensions. 4. **Wait the full window** before judging the result.
Rendering and performance share most of their causes — if you are shipping large client bundles, [the JavaScript SEO diagnostics](/blog/javascript-seo-rendering-problems-diagnosis) will find the same problem from the crawl side, and [our INP and LCP guide](/blog/core-web-vitals-inp-lcp-optimization-guide-for-nextjs) covers the specific fixes.
[Metevix](https://metevix.com/audit) correlates field and lab measurements per template, so you see which real-user problem each lab finding actually explains.
Audit your site for this issue right now.
Metevix crawls your site, ranks what to fix by real impact, and verifies every fix automatically.
Related Technical Articles
Mastering Core Web Vitals: Complete INP, LCP & CLS Optimization Guide
Step-by-step developer techniques to achieve 100/100 Core Web Vitals in Next.js 16 and modern React applications.
Technical SEOJavaScript SEO: How to Diagnose and Fix the Rendering Gaps That Hide Your Content
Why Googlebot indexes an empty page, how to tell client-side rendering problems from crawl problems, and the exact tests that separate the two.
AI Search & GEOllms.txt Explained: A Complete Implementation Guide for AI Search Visibility
What /llms.txt actually is, how retrieval bots use it, how it differs from robots.txt and sitemap.xml, and a production-ready template you can ship today.