Tech SEO

Interaction to Next Paint diagnosis

INP measures how quickly a page responds to user interactions like clicks, taps, and key presses. Good INP (under 200 milliseconds) signals a responsive page. Poor INP (over 500 milliseconds) signals a page that feels broken even when it isn’t.

INP replaced First Input Delay (FID) as a Core Web Vital in March 2024. The change reflected a more comprehensive measurement: FID measured only the first interaction’s input delay, while INP tracks all interactions across the page lifetime and reports the worst (or near-worst) experience. By 2026, INP is the responsiveness metric Google uses for ranking, and the patterns affecting it are different from those that affected FID.


What INP measures:

INP records the latency of all interactions a user has with the page and reports a single value representing the page’s overall responsiveness. The latency for each interaction includes three phases:

Phase What happens
<strong>Input delay</strong> Time between the user action and event handlers starting (waiting for main thread availability)
<strong>Processing time</strong> Time the event handlers spend executing
<strong>Presentation delay</strong> Time between handlers finishing and the next frame being painted

The total for each interaction is the sum of these phases. INP reports the worst interaction (for pages with fewer than 50 interactions) or the worst 2% (for pages with more interactions).

The thresholds:

Performance INP value
<strong>Good</strong> ≤ 200 milliseconds
<strong>Needs improvement</strong> 200 – 500 milliseconds
<strong>Poor</strong> > 500 milliseconds

The 75th percentile threshold applies, similar to LCP and CLS.

The interaction types that count: clicks, taps, key presses, and similar discrete events. Scrolling and continuous gestures don’t count toward INP.


Why INP is harder to fix than FID:

FID only measured the first interaction, which often happened early in the page lifetime when the main thread was busy with initial JavaScript execution. The fix was making initial JS lighter or faster. INP measures all interactions, including:

  • Clicks on dropdowns that trigger expensive UI updates
  • Form input that fires keyup handlers running validation
  • Search boxes that filter results on each keystroke
  • Modal opens that load content dynamically
  • Filter changes that re-render product listings

Each of these is a separate failure mode. A page can have fast initial load and fast first interaction but slow subsequent interactions if any handler does heavy work synchronously. INP catches all of them.

The shift in optimization focus: instead of “load lighter JS,” the question becomes “what makes each interaction slow, and how do we keep handlers fast across the whole page lifetime.”


The recurring causes:

The patterns that cause poor INP cluster into a few categories that recur across most sites where the metric gets diagnosed.

Long-running event handlers are the first cause. A click handler that runs synchronous logic for 300-500ms blocks the next paint by that duration. The handler might be doing data processing, DOM manipulation, calling expensive third-party libraries, or running framework re-renders that touch many components.

Third-party scripts hogging the main thread come next. Analytics, advertising, A/B testing tools, and customer support widgets all run JavaScript on the main thread. A scroll event, a click, or a mouseover that triggers third-party code can produce hundreds of milliseconds of delay.

Large rendering work after user input is a third frequent culprit. The user clicks a filter button; the framework re-renders a list of 500 items; the re-render is slow. INP measures the time until the user sees the result, which includes the re-render.

Layout thrashing during interaction shows up next. The handler reads a layout property, writes a style, reads another property, writes another style. Each read forces the browser to recalculate layout. The cumulative cost stretches the interaction across many frames.

Finally, synchronous third-party calls during interaction. A click handler that makes a synchronous XHR or that calls a heavy library function blocks until the call completes. The user perceives the page as frozen for the duration.


Diagnostic tools for INP:

Identifying which interactions cause poor INP requires tools that capture interaction data.

The Web Vitals JavaScript library is the starting point. It exposes APIs to log INP measurements with attribution data: which event type, which element, how long each phase took. The data can be sent to analytics for analysis.

Chrome DevTools Performance panel comes next. Recording a session while interacting with the page reveals exactly which handlers run, how long each takes, and what blocks rendering. The Web Vitals overlay highlights interactions that scored poorly.

For continuous visibility, field data through real-user monitoring services. SpeedCurve, Cloudflare Browser Insights, New Relic, and others all capture INP from real users, with attribution to specific pages and interaction types. The 75th percentile data shows what the slowest quarter of users experience.

For deep diagnosis, the experimental Long Animation Frames API (LoAF). For browsers that support it, the API exposes detailed information about frames that took longer than 50ms, including which scripts ran during the frame and what blocked rendering.


Optimizing input delay:

Input delay is the gap between user action and the event handler starting. The gap exists because the main thread is busy with other work.

The causes:

  • Long-running JS tasks that started before the interaction and haven’t yielded
  • Garbage collection that pauses execution briefly
  • Other interactions still processing

The fixes:

  • Break up long tasks. A task taking 500ms should be split into smaller chunks of 50ms or less, with await new Promise(resolve => setTimeout(resolve, 0)) or scheduler.yield() between chunks. The main thread becomes available between chunks for new input.
  • Use scheduler.postTask or requestIdleCallback for non-urgent work. Background tasks defer to interactive priority when input arrives.
  • Move heavy computation to Web Workers. Computation that can run off the main thread (data processing, image manipulation, calculations) belongs in workers, leaving the main thread free for interaction.
  • Reduce third-party script work. Audit analytics, ads, and other third-party scripts for excessive main thread usage. Some can be deferred; some can be replaced; some can be removed.

Optimizing processing time:

Processing time is the duration of the event handlers themselves. The optimizations:

  • Make handlers do less synchronous work. A click handler that updates state should update state and let the framework handle re-renders asynchronously, rather than doing the re-render synchronously inside the handler.
  • Defer expensive work. A handler that needs to do heavy computation can use requestAnimationFrame to schedule it before the next paint, or setTimeout(handler, 0) to defer it after the next paint, depending on what the user needs to see.
  • Cache expensive computations. A handler that runs the same calculation repeatedly can cache the result and reuse it.
  • Use efficient algorithms in hot paths. A filter operation running through 10,000 items on every keystroke can become noticeable; using more efficient data structures or pre-filtering can cut the cost dramatically.

For React, Vue, Svelte, and similar frameworks, the optimizations that matter most:

  • Memoize expensive renders. React.memo, useMemo, useCallback (used judiciously) prevent re-renders that don’t need to happen.
  • Virtualize long lists. Rendering 1000 items takes time; rendering only the visible 20 with virtualization (react-window, vue-virtual-scroller) keeps interactions fast.
  • Debounce expensive operations. Search-as-you-type with a 300ms debounce produces 5-10 API calls per minute instead of 100; INP improves and infrastructure costs drop.

Optimizing presentation delay:

Presentation delay is the time between handlers finishing and the next paint actually happening. The optimizations:

  • Avoid layout thrashing in handlers. Read all layout properties first, then write all style changes. The browser can batch the writes without forcing layout recalculation between them.
  • Minimize the changes that trigger layout. Changing transform or opacity doesn’t trigger layout; changing width, height, or position does. When possible, animate the GPU-accelerated properties.
  • Avoid synchronously triggering large re-renders. A state change that triggers re-rendering 500 components can take 100ms. Splitting the change into smaller updates spreads the cost across multiple frames.
  • Use CSS containment. The contain property tells the browser that style changes inside an element don’t affect the surrounding layout. The browser can skip recalculating large parts of the page.

Common patterns that produce poor INP:

Several patterns recur across sites with INP problems.

Search and filter UIs that re-render too much are the most common culprit. Typing in a search box fires keyup events, each of which triggers a filter operation across the entire list. The filter is expensive; INP suffers. The fix is debouncing and virtualization.

Modal opens that load data synchronously come next. The user clicks “view details”; the handler synchronously fetches the data; the modal opens after the fetch. INP measures the full duration. The fix is opening the modal immediately with a loading state, then fetching data asynchronously.

Third-party widgets that block on click show up regularly. Customer support widgets, chat widgets, and similar tools sometimes do expensive work when first clicked. The fix is preloading or warming the widget before the user interacts.

Navigation handlers that render expensive content are another recurring pattern. Clicking a tab triggers rendering of a new view with many components. The rendering takes 400ms; INP records 400ms. The fix is incremental rendering, with the most critical content shown first.

Form validation running synchronously on every input rounds out the list. Each keystroke fires validation that touches multiple form fields. INP suffers per keystroke. The fix is debouncing validation or running it asynchronously.


Frameworks and INP:

Modern frameworks affect INP in ways that have improved substantially since 2021.

React 18 introduced concurrent rendering, which can interrupt long renders to handle input. The benefit shows up as better INP on pages with complex component trees. Earlier React versions completed renders synchronously, which sometimes blocked interactions for 100-500ms.

Vue 3 has similar mechanisms through suspense and async components.

Svelte and Solid produce smaller bundles and faster initial renders, which helps INP at the page-lifecycle level. Their reactive primitives don’t have the same re-render overhead that React’s virtual DOM has, which can help for interactive pages.

The framework choice matters less than implementation discipline. A poorly-written React app has worse INP than a well-written one; the same applies to every framework. The patterns above (debouncing, virtualization, memoization, async work) apply across frameworks.


Mobile INP:

INP is consistently worse on mobile than on desktop for the same reasons LCP is. CPU throttling makes every operation take longer; the same handler that runs in 80ms on desktop might take 250ms on mid-range Android.

The optimization priority follows mobile-first. A site with good mobile INP usually has good desktop INP; the reverse isn’t reliably true.

The specific mobile factors:

  • Touch event handling has different latency characteristics than mouse clicks. Some browsers process touch events through the main thread; others can offload to the compositor.
  • Older devices have weaker CPUs. The 75th percentile mobile experience often reflects 2-3 year old hardware on slower processors.
  • Battery saving modes throttle CPU further, slowing all JavaScript execution.

The implication: mobile INP optimization requires testing on real or simulated lower-end hardware, not just on the developer’s high-end phone.


Common mistakes:

Patterns that recur:

  • Optimizing only the first interaction. Carrying over FID-era thinking misses the broader picture; INP measures all interactions.
  • Lab test scores improving while field data doesn’t. Real users interact with the page in ways automated tests don’t replicate. The metric that matters is field data.
  • Ignoring third-party scripts. Many INP issues come from third-party code that the team didn’t write. The audit has to include them.
  • Adding requestIdleCallback for everything. The callback runs during idle time but can fire later than expected, sometimes degrading perceived performance.
  • Premature optimization with memoization. React.memo and similar tools add complexity. Use them where profiling shows they help; don’t add them speculatively.

Who owns INP in your team:

INP optimization is a discipline applied across the codebase, not a project completed once. Every new feature adds potential interactions; every third-party integration adds potential main thread work. The score reflects the cumulative effect of decisions made over months.

What separates teams with stable INP from teams without: INP budgets per interaction type, monitoring built into CI for performance regressions, and field data alerts that catch degradation in production. The same teams that monitor error rates monitor INP rates; the metric becomes part of the operating baseline.

Sites with consistently good INP tend to treat responsiveness as a product feature, with budgets and ownership the same way error rates have them. When that ownership is missing, the same problems show up across releases: a new feature regresses INP at the 75th percentile, the regression goes unnoticed for weeks, and ranking visibility for affected pages drifts.

INP is the metric the user feels. Long Tasks and click-handler delays are not abstractions to anyone who has clicked a button and watched the browser sit motionless for half a second before responding. The metric makes that experience visible and rankable; the work to improve it is the work of making the page feel like it works.