Google retired First Input Delay last year and replaced it with Interaction to Next Paint (INP). The Web Vitals dashboards updated, the threshold numbers changed, and a lot of people quietly stopped looking.
That was a mistake. INP measures something FID never could: how long your whole interaction took, not just how long the browser took to start handling it.
What INP measures
For every click, tap, or key press during a session:
- The browser starts a clock.
- Your event handler runs.
- Eventually the browser paints whatever you changed.
- The clock stops.
The 75th-percentile longest interaction across the session is your INP.
Why FID was misleading
FID only measured the gap between input and handler start. If your handler took 800ms, then the browser took another 200ms to paint, FID would report 0ms, because the handler started immediately. The user waited a full second.
INP catches the entire delay, which is what the user experiences. A 200ms threshold for “good” is generous in this framing, anything above that and the UI feels sluggish.
What to actually do
A practical workflow:
- Find the slowest interactions in your real user data (Chrome’s Web Vitals extension, RUM tools).
- Profile the worst one. The flame graph almost always shows one of: a sync layout thrash, a long-running event handler, or a cascade of React re-renders that each scheduled the next.
- Break the work into chunks. Yield to the browser between them.
scheduler.yield()is now the right tool; before it landed,setTimeout(0)was the workaround. - Move work off the interaction path entirely where possible. The user clicks, you optimistically update, you do the real work in the background.
The thing I keep saying
Most slow interactions aren’t slow because of the thing the user clicked on. They’re slow because the click handler kicked off a render that kicked off a layout that kicked off another render that finally painted. The fix is rarely “make this part faster”, it’s “do less of this on the interaction path”.