Why does Lighthouse say 87 when real Chrome says 98?.
The ten-point gap between the lab score and a real browser was not in the site but in a single flag of the Chrome the measuring tool starts — and our first diagnosis turned out to be wrong.
One morning our lab score stuck at 87 and our own threshold was 88. Hunting for that single point took us out of the site’s code and into the browser the measuring tool starts. The result has two halves: a single flag in the measurement environment holds the first frame for seconds — and the cause we first blamed for that hold turned out to be wrong.
Hypothesis
The report showed a lab LCP of 3.27 seconds. By that same report’s own lines the page had loaded at 685 ms, render-blocking resources were done by 545 ms, and the main thread was busy for only 202 ms in the first 2.4 seconds. The page was ready; the delay was not in getting ready. That was the hypothesis: what is late is not readiness but the presentation of the first frame.
Method
We built a single-variable A/B. Lighthouse opens Chrome through its own launcher, and that launcher’s default list contains one line: a feature called RenderDocument is switched off. We did not copy the list by hand — we read it from the installed package, removed only that one item, and touched no other flag. Then we built a minimal page carrying the same symptom: a document that answers after 250 ms, one stylesheet that arrives after 150 ms, a heading and a paragraph in the body.
Date and environment
- date → 2026-09-21 measurement · 2026-09-22 repro
- tool → Lighthouse 13.4.1 · mobile profile · lantern
- browser → Chrome 153 · --headless=new · macOS
- subject → this site’s home page + a local minimal page
Result
On the live home page, with the launcher’s default flags, observed first paint stayed at 2,326–2,550 ms across four runs; with only that one feature restored it dropped to 384–425 ms. The performance score moved between 78–87 and 97–98 without a single byte changing on the site. The minimal page showed the same split. In the triggering configuration 18 runs out of 18 stalled; with the feature on, none of 12 did.
- live · tool defaults → first paint 2,326–2,550 ms · 78–87
- live · feature on → first paint 384–425 ms · 97–98
- minimal · defaults → 1,331–1,355 ms (ready at 410 ms)
- minimal · feature on → 423–463 ms (ready at 417 ms)
Our first diagnosis was wrong
On 21 September we blamed cross-document view transitions: switching the transition off removed the hold, switching it back on brought it back. The minimal page refuted that reading — a page with no transition at all was held exactly the same way. The correct sentence is this: what holds the frame is the launcher’s flag; the page transition is only one of the things that can push the first frame into a withheld window. Refuting your own diagnosis is also a measurement result, and it is recorded here.
The browser trace states the decision outright. The compositor’s frame source refuses the page’s frame request because undrawn frames have piled up; the page is fully ready at 413 ms, the next permitted frame arrives at 1,327 ms, and first paint lands 17 ms behind it. With the feature on, the same refusals are there — but the withheld windows fall after the first frame instead of around it.
What we did
We did not change the page, because there was nothing to change. We changed the measurement: the binding lab run now uses the tool’s own flags with that one feature switched back on. The tool’s default number stays in the report under an explicit name — the jury view. An award jury or a client will most likely see that number; both are reported, and neither replaces the other.
Repeat it
- server → document 250 ms · stylesheet 150 ms delayed
- run → lighthouse <url> --form-factor=mobile
- --screenEmulation.mobile --throttling-method=simulate
- arm A → the launcher’s default flags
- arm B → same list, RenderDocument removed from it
- read → audits.metrics … observedFirstContentfulPaint
Limits
We do not know why this feature changes the frame accounting; we only measured that it does, deterministically. We could not run PageSpeed Insights itself — the API quota was exhausted — so the jury-view line also comes from the local tool. We sampled the readiness band in which the hold appears, we did not map it; on another machine its edges will sit elsewhere. The measurement was written as a contribution to an open report in Lighthouse’s own tracker, where the note today reads: no minimal synthetic reproduction found.
The measuring tool’s Chrome is not the visitor’s Chrome.