A client sends a message saying the new site feels instant. Two weeks later Search Console says LCP is failing on mobile. Both are true. The client is on a recent laptop, on office fibre, with every asset already cached, visiting the same five pages they have visited forty times. Nothing about that is a measurement.
This is the most common reason performance work gets deprioritised: the people deciding whether there is a problem have the best possible experience of the site, by construction. Here is where the gap comes from, and what to do instead of trusting your own browser.
Four reasons your experience is not theirs
You have a warm cache
Your second visit is not the visit that matters. Fonts, CSS, the framework bundle and the hero image are all local for you. For a first-time visitor arriving from a search result, every one of those is a network request — and first visits are where almost all of your conversions come from.
Test in a fresh private window, or with the cache disabled in DevTools, every single time. If you have not seen the uncached load, you have not seen the site.
Your CPU is not representative
This is the one people underestimate most, because bandwidth has improved far faster than single-core performance at the low end of the phone market. JavaScript parsing, style recalculation, layout and hydration are all CPU-bound. A mid-range Android that is three years old can take several times as long as your machine to execute the exact same bundle, on the exact same connection.
That is why INP failures are so often invisible internally. The main thread on your laptop finishes the work before you notice; on the device your visitor is holding, the same work is a visible stall between tapping and anything happening.
Latency matters more than bandwidth
Upgrading from 50 Mbps to 500 Mbps changes almost nothing about how fast a page feels. Round-trip time changes everything, because the critical path is a chain of dependent requests: HTML, then the stylesheet it references, then the font the stylesheet references. Each link in that chain pays the latency again.
This is why Lighthouse's default mobile profile throttles to roughly 1.6 Mbps with a 150 millisecond round trip and applies a fourfold CPU slowdown. It is not simulating a bad connection to be unfair; it is simulating mobile reality, where latency is high and variable even when the signal bars look full.
You go to the pages you built
Your habitual route is the home page and two others. Your visitors land on blog posts, a service page deep in the tree, a location page with an embedded map. Performance is per-template, and the template nobody on the team visits is usually the one with the unoptimised hero and the third-party embed.
What the field data sees — and what it misses
Google's field data for Core Web Vitals comes from the Chrome User Experience Report, which is a specific and partial population. Four properties of it change how you should read your own numbers:
- It is Chrome only, from opted-in users. CrUX draws on Chrome users who have usage statistics reporting enabled and meet Google's documented eligibility conditions. Safari and Firefox visits are not in there, which means on most sites a significant share of real traffic — including essentially all iOS Safari traffic — is invisible to it.
- It is the 75th percentile. Your median visitor is irrelevant to the assessment. The slowest quarter of visits sets the result, which is exactly the quarter you never experience yourself.
- It is a 28-day rolling window. A fix you deployed last Tuesday will not be fully reflected for a month, and a regression you introduced is already being averaged in with four good weeks. Both facts make people draw the wrong conclusion from a one-week look.
- It needs traffic to appear at all. Low-traffic URLs get no URL-level data, which is why Search Console groups them and why small sites often see origin-level numbers only.
Browser support also skews what any real-user monitoring tool can tell you. The APIs behind LCP, INP and CLS are Chromium features; Safari does not implement them, so a field library collects nothing for those metrics from iOS visitors. If your audience is iPhone-heavy, your dashboard is describing a minority of your users with confidence and the rest not at all.
How to reproduce reality in twenty minutes
- Look up what your visitors actually use. Your analytics knows the device, browser and country mix. Find the 75th-percentile device, not the modal one. If a quarter of mobile traffic is on Android devices more than three years old, that is your test target.
- Test uncached, throttled, on the templates that get traffic. Private window, cache disabled, CPU throttling on, network throttled. Four templates minimum: home, the top service page, a blog post, and whatever your top landing page is.
- Then test on a real cheap phone. Emulation models the CPU slowdown but not thermal throttling, not a filling storage device, not the browser competing with twelve background apps. Nothing substitutes for holding the device.
- Install real-user monitoring and wait. Google's own
web-vitalslibrary is small and reports the same metric definitions Chrome uses, segmented however you like. This is the only way to see your own distribution rather than Google's sample of it.
js
// Report real-user metrics with the dimensions that matter to you.
import { onLCP, onINP, onCLS } from "web-vitals";
function send({ name, value, rating, navigationType }) {
navigator.sendBeacon(
"/api/vitals",
JSON.stringify({
name,
value,
rating, // "good" | "needs-improvement" | "poor"
navigationType, // cold navigation vs back/forward cache
template: document.body.dataset.template,
effectiveType: navigator.connection?.effectiveType,
deviceMemory: navigator.deviceMemory,
}),
);
}
onLCP(send);
onINP(send);
onCLS(send);Buy the slow phone
The best thing a front-end team can buy is an inexpensive Android handset, kept deliberately un-upgraded, used for every review. It changes the conversation permanently, because performance stops being an abstract score and becomes something everyone in the room has felt.
It also catches a category of problem emulation never surfaces: tap targets that are too small for a thumb, hover states that never fire, a sticky header that eats a third of a short screen, an input that triggers a zoom you cannot escape. Those are not Core Web Vitals, but they are the actual experience.
What this changes about how you work
Three rules we hold to. Never accept "it feels fast to me" from anyone, including ourselves. Never report a Lighthouse score as proof that Core Web Vitals passed — the thresholds are field measurements at the 75th percentile, and the lab cannot measure INP at all. And never ship eleven changes in one release while watching the field numbers, because the window moves slowly enough that you will never learn which one worked.
For what each metric decomposes into and which fixes move it, see what actually moves LCP, INP and CLS. If you want someone to start from your real-user data rather than a score, that is what our speed optimization work is.