Interaction to Next Paint has been in Core Web Vitals since March 2024, replacing the old FID. By mid-2026 it's no longer a metric to keep an eye on: it's the one that gains or loses us ranking positions. And it exposes sites that are "fast on first load and sticky the moment you touch anything".
Why INP is more honest than FID
FID measured only the delay of the first input. A trick: if the first interaction was fast, the score looked good even if the rest of the page responded sluggishly. INP looks at latency across the whole session and reports (almost) the worst case. You can no longer cheat with a light onload.
The "good" threshold is 200ms. "Needs improvement" runs to 500ms. Under 200ms the UI feels instant; above 500ms users feel the lag even without being able to name it.
The real causes we find in audits
- Long tasks from third-party JavaScript: tag managers, chat widgets, analytics. A single marketing script running 300ms on the main thread wrecks the whole page's INP.
- Heavy hydration: giant client components that hydrate all at once on the first tap. The browser is busy mounting React while the user is already clicking.
- Unbroken state updates: a
setStatethat synchronously recomputes a 2,000-row list. The interaction fires, but the next paint lands half a second later. - Layout thrashing: handlers that read and write the DOM in a loop, forcing multiple reflows in a single frame.
What we actually changed
Break long tasks
The most effective lever is the most boring one: break up long work. We use scheduler.yield() where supported to give the main thread back between chunks, and we push any DOM-free computation to a Web Worker. On its own this took pages from 480ms to 180ms.
Isolate third parties
Every third-party script loads with defer, after interaction, or inside an iframe/worker (Partytown still earns its place). Our project rule: no tag runs on the main thread during the first seconds of the page's life, full stop.
Selective hydration
With Next.js and Server Components most of the page stays server-only. We hydrate only the interactive islands. Less JS shipped means less JS to run on the first tap, and INP benefits from that more than LCP does.
Measure in the field, not the lab
Local Lighthouse can't see real INP: it lacks human interaction. We watch CrUX field data and, for detail, send the INP event to our own endpoint via the PerformanceObserver API. The pattern that almost always emerges: 90% of users are fine, and the p75 is ruined by three specific interactions, open menu, apply filter, open cart. You optimize those, not everything.
Verdict
INP rewards serious engineering and punishes the "let's load one more script" habit. You don't need to rewrite the site: you need to profile the three interactions users actually perform and get synchronous work off the main thread. It's the highest return on investment we see on the frontend in 2026.