ANTIGRAVITY LABJP
Articles/Tips & Best Practices
Tips & Best Practices/2026-07-08Intermediate

When Lighthouse Is Green but Search Console's Core Web Vitals Are Red — Field Notes on Naming the Slow Interaction with Real-User Data

Lighthouse scores in the 90s, yet field Core Web Vitals won't budge. Here is how I closed the lab-vs-field gap with real-user monitoring (RUM), named the exact interaction driving a slow INP, and fixed it with Antigravity.

antigravity422core-web-vitalsINPRUMweb-performance

Premium Article

My Lighthouse score was 92. Green. Green every time I ran it.

And yet the Core Web Vitals report in Search Console kept INP stuck on "needs improvement." Touching it on a real device, honestly, it did not feel that slow.

As an indie developer running a small blog site on my own, this mismatch jerked me around for about two weeks. I spent that time raising the lab number, and the field number did not move a single millisecond.

The cause was simple. I had been measuring a screen that real users were not touching. This is a record of closing the lab-vs-field gap with real-user monitoring, naming the slow interaction, and only then fixing it with Antigravity.

Internalize that lab and field are different things

First I re-learned exactly what Lighthouse measures.

Lighthouse is "lab data." It is nothing more than one load, on your machine, under fixed conditions. INP in particular barely fires any interactions in the lab, so it usually comes out near zero. Of course it looks green.

Search Console, on the other hand, shows "field data": the real-user p75 from the Chrome User Experience Report (CrUX). It is the distribution of what happens when actual people press buttons, type into forms, and filter lists.

AspectLab (Lighthouse)Field (CrUX / Search Console)
What it measuresOne synthetic load28 days of real-user distribution
How it treats INPFew interactions; tends to understateReflects the p75 of real interactions
Update speedImmediateDays to weeks of lag
Used for SEO evaluationNoYes

Field data is what affects ranking. So if lab is green but field is red, the one to trust is the field. Until this sank in, I kept shooting at the wrong target.

Measure real users' INP yourself

CrUX is useful, but it is coarse and lagging. It will not tell you "which page, which interaction is slow." So I instrumented real-user monitoring (RUM) on my own site.

Google's web-vitals library has an attribution build, and that was decisive. It does not just return the INP value — it tells you the exact element and event that caused the delay.

// Collect real users' INP with its source
import { onINP } from 'web-vitals/attribution';
 
onINP((metric) => {
  const attr = metric.attribution;
  const payload = {
    value: Math.round(metric.value),          // the actual INP in ms
    rating: metric.rating,                     // good / needs-improvement / poor
    target: attr.interactionTarget,            // selector of the DOM element that caused the delay
    type: attr.interactionType,                // pointer / keyboard
    // breakdown: where the time went — input delay, processing, or presentation
    inputDelay: Math.round(attr.inputDelay),
    processingDuration: Math.round(attr.processingDuration),
    presentationDelay: Math.round(attr.presentationDelay),
    path: location.pathname,
  };
  // send lightly via beacon (survives page unload)
  navigator.sendBeacon('/api/rum', JSON.stringify(payload));
});

The interactionTarget and the three breakdown fields I send here were the treasure map. INP is the sum of input delay, processing duration, and presentation delay. Which one is fat completely changes the fix you should reach for.

I accumulated a week and aggregated by path and target. It turned out that INP p75 hit 410ms not on the homepage I had been measuring in Lighthouse, but on the tag filter of the article list. That is where most real users were interacting. I had been polishing an entrance no one walked through.

The mindset of turning measurement into continuous monitoring is the same as in Measuring Antigravity CLI startup latency with hyperfine: the starting point is holding the source of the number in your own hands.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Why lab (Lighthouse) and field (CrUX/RUM) diverge, and which one to trust for ranking
Using the web-vitals attribution build to pinpoint the exact DOM element and event behind a slow INP
Handing that one named interaction to Antigravity to fix, then protecting the field p75 with a regression test
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Tips2026-06-20
Keeping Scheduled Runs Reproducible: Pinning the Antigravity CLI Version to Tame Behavior Drift
The Go-based Antigravity CLI is now available to everyone, and updates are landing at a quick pace. When a CLI baked into your automation upgrades underneath you, a single morning's job can behave differently. Here is how I keep things reproducible — pinning the binary, recording its identity in each run's log, and rolling upgrades forward one job at a time — drawn from running four sites on an overnight schedule.
Tips2026-06-17
Three Prompts I Tried When Antigravity's Code Felt Correct But Not Mine
When Antigravity's output runs but never quite fits your codebase, the gap is usually missing design context. Three prompting patterns for handing over intent — plus the cases where even that wasn't enough, from real indie development.
Tips2026-06-16
Measuring the Go-Based Antigravity CLI's Responsiveness to Rethink My Nightly Batch
The Antigravity CLI was reimplemented in Go, and startup and first-response feel different now. I measure startup, time-to-first-token, and throughput as three separate intervals, then use those numbers to move my nightly batch from serial to parallel.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →