Fixing INP: The Hardest Core Web Vital to Pass
When Google retired First Input Delay and promoted Interaction to Next Paint to a Core Web Vital in March 2024, it was not a minor measurement tweak. FID only captured the delay before the browser started handling an event. INP captures the full cost: the input delay, the processing time, and the presentation delay before the next frame is painted. Sites that sailed through FID with 97% pass rates suddenly found only about 65% clearing the INP threshold.
The 43% failure rate makes INP the most commonly failed Core Web Vital in 2026. The good threshold is under 200 milliseconds; poor is above 500 milliseconds. Those numbers feel generous until you add up a tag manager firing three analytics tags, a React re-render traversing a large component tree, and a synchronous DOM read forced in an event handler. You can easily hit 600 milliseconds on an interaction that feels simple.
This guide is for engineers and SEOs who need to move INP scores into the green. It covers the profiling workflow, the specific patterns that cause high INP, and the practical code changes that shrink interaction latency. Dubai's mobile-dominant market means your worst INP scores are happening on mid-range Android devices, not the MacBook Pro your developer is testing on.
What INP Actually Measures
INP samples every interaction during a page session: every click, every tap, every keypress. It takes the worst interaction latency, with a small allowance for outliers on long sessions. The latency for each interaction has three components: input delay (how long before the event handler runs), processing time (how long the handler takes), and presentation delay (how long until the next frame is painted after the handler finishes).
This three-part structure is why INP is hard to fix. FID only exposed input delay, which is usually caused by a long task already running on the main thread when the user clicks. Processing time and presentation delay expose JavaScript work that happens in direct response to the interaction, including React re-renders, third-party callbacks, and DOM mutations that trigger style recalculation and layout.
Profiling INP in Chrome DevTools
Open DevTools, go to the Performance panel, and record while performing the interaction you suspect is slow. Look for long tasks (red markers on the main thread) that coincide with your click or tap event. The flame chart will show you exactly which function is consuming the most time. Common culprits are React's reconciliation cycle, lodash utilities called synchronously in event handlers, and third-party analytics libraries.
The Interactions track in the Performance panel (added in Chrome 110) shows each interaction with its total INP latency broken into the three phases. This is far more useful than guessing. If the input delay is high, something is blocking the main thread before your handler runs. If processing time is high, your handler is doing too much work. If presentation delay is high, the browser is struggling to paint after your handler finishes.
Breaking Up Long Tasks with scheduler.yield()
The fundamental fix for high processing time is to break long synchronous work into smaller chunks and yield back to the browser between chunks. The Scheduler API's scheduler.yield() function does this cleanly. Instead of running 400ms of work in one block, you run 40ms, yield, run 40ms, yield, and so on. The browser can paint a frame and process higher-priority input between your chunks.
This pattern is particularly important for interactions that trigger expensive data processing: filtering a large list, computing totals, or updating a complex UI state. The visual update that the user expects (button state change, spinner appearing) should happen first before the heavy computation begins. Show the user the response, then do the work.
- Use scheduler.yield() to split long event handlers into browser-yieldable chunks
- Prioritize the visual response (show spinner, disable button) before starting heavy computation
- Move non-UI work to a Web Worker to keep the main thread free for rendering
- Use requestIdleCallback for low-priority work that does not need to happen immediately
- Avoid calling synchronous layout properties like offsetHeight inside event handlers
Third-Party Scripts: The Hidden INP Tax
Third-party scripts are a major source of INP failures because they run on the same main thread as your code. A tag manager that fires on every click, loading additional tracking pixels, can easily add 100 to 200ms of processing time to an interaction. The user experience impact is real: buttons feel sluggish, form fields lag, navigation feels sticky.
Audit every third-party script with the Network panel and the Coverage panel in DevTools. For scripts that must fire on interaction, consider using a facade or delayed loading pattern. Load the actual third-party library on the first user interaction (using a once event listener) rather than at page load. For tag managers specifically, reduce the number of tags firing on each event and use server-side tagging where possible to move processing off the client.
- Audit third-party scripts with Chrome DevTools Coverage panel to find unused code
- Delay non-essential third-party loads until after the first user interaction
- Use server-side tagging to move analytics processing off the client main thread
- Replace heavy widget scripts (chat, reviews) with lightweight facades that load on demand
- Set a performance budget for third-party JavaScript bytes loaded on first interaction
React and Framework-Specific INP Issues
React applications are particularly prone to high INP because a single state update can trigger a re-render of a large component tree. In React 18, concurrent rendering and the useTransition hook let you mark state updates as non-urgent, deferring the expensive re-render to a lower priority and keeping the immediate visual response snappy. Wrapping heavy computations with useDeferredValue prevents them from blocking the interactive update.
For older React applications, the practical advice is to memoize expensive components with React.memo and useMemo, reduce the number of components that re-render on any given state change, and profile with the React DevTools Profiler to find components with unexpectedly high render times. A component that takes 80ms to render is a long task every time it updates.
Measuring INP in the Field
The web-vitals JavaScript library makes it straightforward to capture real-user INP data. Import the onINP function and send the metric value to your analytics platform. Segment the results by device category and page type to find where your worst scores live. A checkout page with high INP is more urgent to fix than an about page because the interaction cost at checkout directly loses sales.
The attributionBuild version of web-vitals provides additional detail including which element was interacted with and which phase (input delay, processing, presentation) dominated the latency. This attribution data turns raw field numbers into actionable debugging leads.
Validating Fixes Before Shipping
Use Chrome DevTools with CPU throttling set to 4x to simulate a mid-range Android device. Run through the key interactions on your page and check the Interactions track for latency above 200ms. This is not a substitute for field data but it will catch the worst offenders before they reach production.
After deploying fixes, wait 28 days for CrUX data to reflect the improvement. You can monitor progress earlier using the PageSpeed Insights API on specific URLs, which shows recent field data percentiles. Set up automated PageSpeed API checks in your monitoring dashboard to get weekly snapshots of field INP for your key page templates.
INP is hard because it measures the full cost of every interaction, not just the first. The 43% failure rate in 2026 reflects how many sites carry heavy JavaScript that blocks the main thread during clicks and taps. Fixing INP means profiling real interactions, breaking up long tasks, deferring third-party scripts, and using framework-level tools like React concurrent rendering to keep visual responses immediate. For any site where users need to interact to convert, a poor INP score is a conversion problem as much as a ranking problem.
Frequently asked questions
What is a good INP score for my website?
Good INP is under 200 milliseconds at the 75th percentile of user interactions. Needs improvement is 200 to 500 milliseconds, and poor is above 500 milliseconds. Aim for under 150ms as a working target to give yourself headroom against the 200ms threshold at the 75th percentile.
Why did my INP score get worse after adding a new feature?
New features usually add JavaScript that runs on interaction. Even a small addition to an event handler can push a borderline interaction over 200ms. Profile the interaction with Chrome DevTools Performance panel immediately after shipping to identify the new code responsible and consider lazy-loading or deferring it.
Does INP affect mobile more than desktop?
Yes significantly. Mobile CPUs are slower at executing JavaScript, meaning the same code takes longer to process. An event handler that runs in 80ms on a MacBook Pro may take 200 to 300ms on a mid-range Android device. Always test INP with CPU throttling enabled in DevTools.
Can I fix INP without a developer?
Partially. Removing unnecessary third-party scripts via a tag manager audit, reducing the number of tags firing on interactions, and deferring non-critical scripts are changes that do not always require code changes. But the deepest INP fixes involving JavaScript refactoring require developer involvement.
Does INP only measure click events?
INP measures clicks, taps, and keypresses. It does not measure scroll, zoom, or hover events. For text-heavy pages, keypress latency in search fields or form inputs is a common source of poor INP scores that gets overlooked if testing focuses only on button clicks.