Zum Inhalt springen
Core Web Vitals specialists
All Articles Core Web Vitals

Optimizing INP: Improving Interaction to Next Paint

13 min read
INPCore Web VitalsPerformance

Since March 2024, Interaction to Next Paint (INP) has been an official Core Web Vital, fully replacing First Input Delay (FID) (Google web.dev, 2024). Where FID only measured the delay of the very first interaction, INP evaluates every single user action across the entire page visit. For many websites it is by far the hardest of the three Core Web Vitals metrics, because it depends directly on JavaScript execution on the main thread. This article explains how INP works technically, how to recognize poor scores and which concrete measures bring latency below the 200-millisecond threshold -- from long tasks through event handlers to third-party scripts.

Interaction to Next Paint - Anatomy of an InteractionClick / Tap / Key press until the next frame1. Input Delay40msMain thread busy with a long task2. Processing Time95msEvent handler execution3. Presentation Delay30msRendering until next frameINP ThresholdsGood< 200msNeeds Work200-500msPoor> 500msSum = INP value165msInputProcessingPaintSlowest interaction is reported (75th percentile)Break up long tasksscheduler.yield()Chunking, yieldingSlim down handlersrequestIdleCallbackOffload to Web WorkerTame third partiesasync, deferLazy on interactionBatch DOM workcontent-visibilityAvoid layout thrashingMeasure in the field, not the labChrome UX Report | web-vitals.js | PageSpeed Insights | Long Animation Frames API

What INP measures and why it is so hard to optimize

INP measures the responsiveness of a website across the entire session. For every interaction -- a click, a tap on the touchscreen or a key press -- the browser records the time between the input and the next visible screen update. At the end of the visit, the slowest (more precisely, near-slowest) interaction is reported as the INP value. The threshold of 200 milliseconds is considered good, up to 500 milliseconds needs improvement and anything above is poor (Google web.dev, 2024). Unlike FID, it is no longer enough for the first action to be fast -- every filter change, every menu opening and every click on the cart button counts.

This is precisely what makes INP the most demanding metric. According to evaluations in the HTTP Archive Web Almanac (2024), roughly three quarters of mobile websites achieve a good INP value, whereas the pass rate for the predecessor metric FID was close to 100 percent (HTTP Archive Web Almanac, 2024). The jump in difficulty is no accident: INP exposes structural problems in the JavaScript architecture that FID systematically overlooked. Anyone serious about frontend optimization has to rethink the work done on the main thread from the ground up.

The central bottleneck is the main thread -- the only thread in the browser that simultaneously executes JavaScript, computes layout and triggers rendering. If this thread is occupied by a long-running task, the browser cannot process a waiting user interaction. The input lands in a queue and is only handled once the thread is free again. This very wait time enters the INP value as input delay. Optimizing INP therefore means, above all, keeping the main thread free and ready to respond.

Understanding the three phases of an interaction

Every interaction breaks down into three measurable phases whose sum yields the INP value. Anyone who wants to optimize must first know which phase is losing time -- because the countermeasures differ fundamentally. The input delay is the time between the user action and the start of the corresponding event handler. It almost always arises because the main thread is still busy with another task at the moment of input. The processing time is the pure execution duration of the event handlers. The presentation delay is the time the browser needs after the handler to compute style, layout and paint of the next frame.

Input Delay

The main thread is blocked by a running task when the input arrives. Fix: break up long tasks, spread out script execution during initial load, schedule less work at startup.

Processing Time

The event handler itself runs too long. Fix: do only what is visually necessary immediately, defer heavy computations or offload them to Web Workers, avoid expensive layout reads.

Presentation Delay

Rendering the next frame takes time. Fix: keep DOM updates small, use content-visibility for offscreen regions, avoid large synchronous layout calculations.

This breakdown is the most important diagnostic lever. A high input delay points to problems during initial load -- typically large JavaScript bundles that block the thread while hydrating. A high processing time indicates heavy event handlers, such as synchronous data processing or extensive DOM manipulation directly inside the click handler. A high presentation delay, finally, results from expensive rendering, for instance when a single click triggers a full layout recalculation across thousands of DOM nodes. Only once it is clear which phase dominates can you optimize in a targeted way.

Measuring INP correctly: field before lab

Unlike LCP, INP cannot be measured reliably in the lab. Lighthouse and synthetic tests do not perform real user interactions, which is why their INP estimates can deviate considerably from reality. Google uses exclusively field data from the Chrome UX Report (CrUX) for evaluation, aggregated across the 75th percentile of all users (Google web.dev, 2024). This means optimization must be guided by real user data, not by an isolated lab score. PageSpeed Insights shows both the CrUX field data and the lab diagnostics and is therefore the first port of call for an initial assessment.

For ongoing observation in real operation, Real User Monitoring (RUM) is recommended. Google's open-source library web-vitals.js captures INP directly in each visitor's browser and provides, per interaction, the target element as well as the breakdown into the three phases (Google web.dev, 2024). Since 2023 the Long Animation Frames API (LoAF) has also been available, which breaks down individual long-running frames including the scripts responsible (W3C, 2024). Combined, these tools enable a page-level attribution: which interaction on which template is slow, and which script is responsible? This very attribution is the starting point of any structured performance analysis.

Practical tip: debugging INP in the field

Use a PerformanceObserver with type 'event' and a durationThreshold to capture slow interactions directly in real users' browsers. Each entry provides the interaction latency, the event type and the target element. Send this data in batches via requestIdleCallback to your monitoring -- this way the measurement itself does not worsen the INP value. Aggregated, the data reveals which elements and templates cause the worst scores.

Breaking up long tasks: the most effective lever

A long task is any JavaScript execution that blocks the main thread for more than 50 milliseconds at a stretch (W3C Long Tasks Specification). During a long task the browser cannot process input -- every interaction in this window starts with a corresponding input delay. Long tasks are therefore the most common single cause of poor INP values. The solution is not to eliminate the work, but to split it into smaller chunks and hand control back to the browser in between (yielding).

The modern tool of choice is the scheduler.yield() API, available in stable versions since Chrome 129 (Google web.dev, 2024). It interrupts a running task, lets waiting interactions go first and then resumes the work with high priority -- in contrast to the classic setTimeout(0), which puts the continuation at the end of the queue. Where scheduler.yield() is not yet available, a setTimeout call serves as a fallback. The important thing is to break at natural boundaries: after each processed element of a long loop, or between logically completed steps of work.

yield-in-long-loop.js
// Break long processing into chunks and regularly hand
// control back to the browser (yielding).

async function yieldToMain() {
  if ('scheduler' in window && 'yield' in scheduler) {
    return scheduler.yield();
  }
  // Fallback for browsers without scheduler.yield()
  return new Promise((resolve) => setTimeout(resolve, 0));
}

async function processItems(items) {
  let lastYield = performance.now();

  for (const item of items) {
    handleItem(item); // expensive per-item work

    // Yield after more than 50ms of uninterrupted work
    if (performance.now() - lastYield > 50) {
      await yieldToMain();
      lastYield = performance.now();
    }
  }
}

The example shows the basic pattern: instead of processing a long loop in one go, the code measures the elapsed time and hands over control after roughly every 50 milliseconds. A user interaction that arrives during this time is processed immediately, rather than waiting until the entire loop completes. In practice, two further strategies combine well: moving non-urgent work into the browser's idle phases via requestIdleCallback, and rendering what is visible first before processing offscreen regions. This prioritization by visibility noticeably reduces perceived latency.

Slimming down event handlers and deferring work

The second phase -- the processing time -- is determined directly by the work inside the event handler. A common misconception is that the handler must do everything immediately on a click. In reality it is enough to deliver the visual feedback instantly and defer all remaining tasks. Someone who presses a button expects the button to change at once -- whether a tracking event is sent or a record is recalculated in the background is secondary for perceived responsiveness and belongs at the heart of any frontend optimization. Splitting work into 'immediately visible' and 'can wait' is the key to short handlers.

Concretely, this means: the handler performs only the immediate DOM change, then yields, and only afterward run analytics, persistence or follow-up computations. Compute-intensive operations without a DOM relationship -- sorting large lists, data parsing, image processing, encryption -- belong in a Web Worker that runs on its own thread and fully relieves the main thread. For input fields and scroll events, debouncing and throttling prevent every key press from triggering expensive processing. These techniques feed directly into the processing time.

INP symptomTypical causePhaseEffective countermeasure
First clicks feel sluggishLarge JS bundle blocks during hydrationInput DelayCode splitting, less JS at startup, yielding
Filters and sorting stallSynchronous recalculation in the handlerProcessing TimeWeb Worker, debouncing, incremental rendering
Menus open with a delayJavaScript animation instead of CSSPresentation DelayCSS transitions, transform instead of layout properties
Typing in the search field jittersProcessing on every key pressProcessing TimeDebouncing, requestIdleCallback
Click on a long list is slowLayout recalculation across many nodesPresentation Delaycontent-visibility, virtualization
Response after page load stuttersThird-party scripts load the threadInput Delayasync/defer, lazy load on interaction

The table makes clear that the same symptom -- a sluggish interaction -- can have very different causes. Without the phase diagnosis from field data, there is a risk of optimizing in the wrong place. A team that invests weeks in slimming down event handlers, when the actual problem is a blocking third-party script during load, barely improves the INP value. This is why measurement always comes first, before a single line of code is changed.

Third-party scripts: the underrated INP killer

Analytics tags, consent managers, chat widgets, A/B testing tools and social media embeds run on the same main thread as your own application code. They are one of the most common causes of poor INP values, because they perform work over which the operator has only limited control. Particularly problematic are scripts that register global event listeners and run along with every interaction -- such as heatmap and session-recording tools that capture every click and every mouse movement. This invisible load adds up over the visit and pushes the INP value higher.

The most effective measure is a consistent loading strategy. Scripts that are not needed for the first screen render are loaded with async or defer, ideally only after the first user interaction or when entering the visible area (Intersection Observer). A chat widget does not need to be fully loaded at page load -- it is enough to show a lightweight placeholder and load the actual widget on the first click. For tracking, it is worth considering server-side solutions and a first-party proxy that takes the load off the user's browser.

  • Assess each third-party script individually for its INP impact rather than trusting it blanketly
  • Load non-critical scripts only after the first interaction or on scroll
  • Lazy-load chat widgets and heavy embeds on click instead of at page load
  • Limit global event listeners from tracking tools to the bare minimum
  • Keep the consent manager lean and do not let it block the entire render
  • Send tracking events via requestIdleCallback instead of synchronously in the click handler

Responsiveness is conversion-relevant

INP is more than a technical value for ranking. A website that responds noticeably to every click conveys quality and trust. Delays of half a second feel like a defect in the checkout, in filtering or during search -- users double-click, abandon or leave the page. Optimizing INP therefore improves not just a Core Web Vital, but the economically decisive perception of the entire application.

Shortening rendering and presentation delay

The third phase -- the presentation delay -- is often overlooked but can contribute substantially to the INP value. It arises when the browser has to do a lot of work for the next frame after the event handler: style computation, layout and paint across a large part of the document. A classic trigger is a DOM change that causes layout thrashing -- repeatedly reading and writing layout properties in alternation, forcing the browser into multiple synchronous recalculations. The solution is to batch all reads and only then perform all writes.

The CSS property content-visibility: auto lets the browser initially exclude offscreen regions from rendering and only compute them once they enter the visible area (Google web.dev). This significantly reduces the amount of layout work per frame, especially on long pages with many sections. For animations, the rule of thumb is to animate exclusively the transform and opacity properties, which the browser can process on a separate compositing layer without recalculating layout. Animating properties like width, height or top, by contrast, forces expensive layout passes and lengthens the presentation delay.

INP forces us to be honest: a page is not fast because it loads quickly, but because it responds to every user action immediately. The first second belongs to loading -- every second after that belongs to responsiveness.

From project work on Core Web Vitals optimization

A typical INP optimization path in practice

A recurring pattern from practice shows how the measures interlock. Starting point: an online shop based on Shopware CE reports an INP value in the needs-improvement range in the Chrome UX Report, clearly above 200 milliseconds -- a frequent scenario in Shopware performance optimization. The field data identifies the product listing page with its filters as the biggest contributor. The phase diagnosis via the Long Animation Frames API shows that the bulk of the latency arises in the processing time -- on every filter change, the entire product list is recalculated and re-rendered synchronously (project experience).

The optimization path tackles three points. First, the filter recalculation is decoupled from the synchronous click handler and broken into smaller steps with yielding, so the list updates incrementally without blocking the thread. Second, two tracking scripts that previously sent their events synchronously inside the filter handler are switched to requestIdleCallback. Third, content-visibility reduces the rendering load for the numerous product tiles below the visible area. In sum, the INP value moves into the good range -- without removing a single feature (project experience). Comparable starting points appear in many projects across industries and template types.

Crucial is the final validation in the field. Because CrUX data updates as a rolling 28-day average, the effect of an optimization only shows up in the official values after several weeks. Until then, your own Real User Monitoring provides the faster feedback channel. This very combination of diagnosis, targeted measure and field validation sits at the center of every Core Web Vitals optimization we implement for shops and corporate websites.

Keeping INP healthy: monitoring and budgets

A good INP value is not a final state but must be actively maintained. Every new third-party script, every plugin update and every additional feature can add load to the main thread. INP therefore belongs in continuous monitoring with threshold alerts that report a regression before it affects ranking. Monitoring at the template level is decisive: the origin score in CrUX may be good while a single high-traffic template -- such as the checkout -- delivers poor values and thus quietly costs revenue.

In addition, performance budgets prove their worth in the development process. An upper limit on the amount of JavaScript executed during initial load prevents the input delay from creeping up as bundles grow. Continuous integration tools check these budgets on every deployment and raise a flag as soon as a limit is exceeded -- before the change goes live. This way the hard-won responsiveness is preserved across many releases. The combination of field-data monitoring and budget control is an integral part of our performance services -- for an initial assessment of your INP values, arrange a no-obligation initial consultation.

INP in concert with the other vitals

INP concerns interactivity, LCP concerns loading time and CLS concerns visual stability. Measures overlap: a leaner JavaScript bundle improves both the input delay (INP) and render blocking (LCP). Relieving the server and using HTTP/3 speeds up loading and frees up main-thread headroom earlier. A holistic optimization therefore never addresses just one metric in isolation.

A look at the transport layer is worthwhile too: faster delivery of resources shortens the window in which the main thread is busy with the initial load, indirectly reducing the input delay. How modern protocols help here is explained in our article on HTTP/3 and QUIC for shop performance. Combined with the main-thread measures described here, the result is an overall picture in which loading and interaction speed reinforce one another.

This article is based on data from: Google web.dev Web Vitals and INP documentation (2024), Chrome UX Report (CrUX) methodology (2024), HTTP Archive Web Almanac (2024), W3C Long Tasks and Long Animation Frames specification (2024). The thresholds and recommendations reflect the state of June 2026.