OctaneAudit
Core Web Vitals

INP vs FID: What Changed When INP Replaced FID in 2024

FID measured one delay on one interaction. INP measures the full latency of nearly every interaction. Here is what changed and how to fix a failing INP.

OCOctaneAudit Team9 min read
Core Web Vitals

INP vs FID: What Changed When INP Replaced FID in 2024

On 12 March 2024, Interaction to Next Paint (INP) replaced First Input Delay (FID) as the responsiveness metric in Core Web Vitals. Many sites that had passed FID for years suddenly showed "Needs improvement" or "Poor" in Search Console, without a single line of code changing.

That was not a bug. INP measures something FID never looked at. This article explains exactly what is different, why Google made the switch, and how to diagnose and fix a failing INP score on a real site.

What FID measured, and why it was too easy to pass

FID recorded one number: the time between a user's first interaction with a page (a click, tap or key press) and the moment the browser was able to start running the event handlers for it.

Two limits made it a weak signal:

  1. Only the first interaction counted. If the first tap was fast and every tap after it froze the page for 800 milliseconds, FID still reported a good score.
  2. Only the input delay counted. FID stopped the clock when the handler started. The time spent running the handler, and the time spent rendering the result, were ignored entirely.

In practice, most sites passed FID comfortably on both desktop and mobile. A metric that almost everyone passes does not tell you much about how responsive a page actually feels.

What INP measures instead

INP observes every click, tap and keyboard interaction during the whole page visit. For each one it measures the full latency, from the user's input until the browser paints the next frame that reflects it. Hover and scroll are not included.

Each interaction's latency has three parts:

PhaseStartsEndsTypical cause when slow
Input delayUser inputEvent handlers beginOther JavaScript already running on the main thread
Processing durationFirst handler beginsLast handler finishesHeavy handler code, synchronous state updates, large re-renders
Presentation delayHandlers finishNext frame is paintedStyle recalculation, layout and paint of a large DOM

FID only ever covered the first row, and only for one interaction. INP covers all three rows for nearly every interaction.

At the end of the visit, the page's INP is the slowest interaction observed. On pages with many interactions, one outlier is dropped for every 50 interactions, so a single unlucky hiccup on a long session does not dominate the score.

The thresholds

RatingFID (retired)INP (current)
Good100 ms or less200 ms or less
Needs improvement100 to 300 ms200 to 500 ms
PoorOver 300 msOver 500 ms

As with every Core Web Vital, the assessment uses the 75th percentile of real-user page loads, split by mobile and desktop. To pass, 75% of visits need an INP of 200 milliseconds or less.

Why sites that passed FID fail INP

The patterns we see most often when a site flips from passing to failing:

  • Heavy click handlers. A "Filter" button that re-sorts and re-renders 200 product cards synchronously. FID never measured the processing time; INP does.
  • Framework re-renders. In React, Vue and similar frameworks, one state change near the root of the component tree can re-render most of the page. The handler is short, but the work it triggers is not.
  • Third-party scripts. Tag managers, analytics, chat widgets and consent tools often attach their own listeners to clicks, or run long tasks at random times that land in an interaction's input delay.
  • Large DOM size. Pages with many thousands of elements take longer to recalculate style and lay out after every change, which inflates presentation delay.
  • Interactions after load. Opening a mega menu, expanding an accordion or adding to cart. FID only saw the first one; INP sees all of them.

Mobile is almost always worse than desktop. Mid-range Android phones have far slower CPUs than developer laptops, so a handler that takes 40 ms on your machine can take several times longer on a customer's phone.

Step 1: Find the slow interactions in the field

Lab tools cannot tell you which interactions real users perform. Start with field data.

  • Search Console Core Web Vitals report. Shows which URL groups fail INP on mobile and desktop. It tells you where, not why.
  • PageSpeed Insights. Shows the 75th percentile INP from the Chrome UX Report for the URL and the origin, when there is enough traffic.
  • Your own real-user monitoring. The only way to learn which element was clicked and which phase was slow.

The web-vitals library's attribution build gives you everything needed to debug:

import { onINP } from 'web-vitals/attribution';

onINP(({ value, rating, attribution }) => {
  const payload = {
    value: Math.round(value),
    rating,
    target: attribution.interactionTarget,
    type: attribution.interactionType,
    inputDelay: Math.round(attribution.inputDelay),
    processing: Math.round(attribution.processingDuration),
    presentation: Math.round(attribution.presentationDelay),
    loadState: attribution.loadState,
    page: location.pathname,
  };
  navigator.sendBeacon('/rum', JSON.stringify(payload));
});

After a week of data, group by target and look at the 75th percentile. You will usually find that a handful of elements, such as a filter control, a menu toggle or an add-to-cart button, account for most of the poor interactions.

Step 2: Reproduce and profile in the lab

Once you know which interaction is slow, reproduce it in Chrome DevTools:

  1. Open the Performance panel and enable CPU throttling (4x or 6x slowdown) to approximate a mid-range phone.
  2. Start recording, perform the interaction, stop recording.
  3. In the Interactions track, find the interaction. DevTools shows its total duration split into input delay, processing and presentation delay.
  4. Look at the Main track underneath. The long tasks during the interaction show you exactly which functions ran.

Lighthouse's default navigation mode cannot measure INP because nobody interacts with the page. Use Lighthouse timespan mode to record a user flow, or rely on Total Blocking Time as a lab proxy: high TBT strongly suggests the main thread is busy enough to delay interactions.

For harder cases, the Long Animation Frames API (available in Chrome since version 123) reports which scripts contributed to slow frames, including third-party scripts by source URL. The web-vitals attribution build exposes these entries as longAnimationFrameEntries.

Step 3: Fix the phase that is slow

Reduce input delay

Input delay means the main thread was already busy when the user acted.

  • Break up long tasks that run during and after load. Any task over 50 ms can block an interaction.
  • Defer non-critical third-party scripts. Load chat widgets on first interaction or after the page is idle, not in the head.
  • Audit tag manager triggers. Tags firing on "All Clicks" run in front of your own handlers on every tap.
  • Avoid hydrating the whole page at once. If your framework supports partial or progressive hydration, use it for below-the-fold components.

Reduce processing duration

The goal is to do the minimum work needed to give visual feedback, then yield to the browser so it can paint, then finish the rest.

function yieldToMain() {
  if (globalThis.scheduler?.yield) {
    return scheduler.yield();
  }
  return new Promise((resolve) => setTimeout(resolve, 0));
}

filterButton.addEventListener('click', async () => {
  filterButton.classList.add('is-loading'); // instant visual feedback
  await yieldToMain();                       // let the browser paint it

  const results = applyFilters(products);    // heavy work after the paint
  await yieldToMain();
  renderResults(results);
  sendAnalytics('filter_applied');
});

scheduler.yield() is supported in Chromium-based browsers; the setTimeout fallback covers the rest. Other techniques that consistently help:

  • Move analytics calls and other non-visual work out of the handler, or behind requestIdleCallback.
  • Debounce input handlers on search boxes rather than filtering on every keystroke.
  • In React, wrap expensive non-urgent updates in startTransition so the urgent update (the button state) paints first.
  • Memoize large lists and avoid putting fast-changing state at the top of the component tree.

Reduce presentation delay

  • Shrink the DOM. Virtualize long lists and avoid rendering hidden content such as every mega menu panel at once.
  • Use content-visibility: auto on large off-screen sections so the browser skips their rendering work.
  • Avoid layout thrashing. Reading layout properties (like offsetHeight) right after writing styles forces synchronous layout. Batch reads before writes.
  • Keep CSS selectors and animations cheap. Animate transform and opacity, not width, top or box-shadow.

Step 4: Verify and watch the trend

INP fixes are easy to regress. A new tag, a new feature or a dependency upgrade can add 100 ms to a handler without anyone noticing.

  1. Re-profile the interaction with the same CPU throttling and confirm each phase shrank.
  2. Ship, then watch your real-user data for the specific target you fixed.
  3. Expect Search Console to lag: its data is a rolling 28-day window, so the status changes gradually over about a month.
  4. Add a performance budget for Total Blocking Time in CI so regressions get caught before release.

If you would rather not build that alerting yourself, OctaneAudit Monitoring checks your key pages daily and flags Core Web Vitals regressions as they appear.

INP and the other Core Web Vitals

INP sits alongside Largest Contentful Paint and Cumulative Layout Shift. The fixes sometimes overlap: deferring heavy scripts improves both INP and LCP render delay. They can also conflict. Lazy-hydrating a component improves INP but can cause layout shift if its placeholder has no reserved size.

For the full picture of how the three metrics work together, see the Core Web Vitals developer guide. If LCP is also failing, the LCP playbook covers it phase by phase, and our guide to CLS covers layout shift. For sites that render heavily on the client, the rendering trade-offs in JavaScript SEO and Googlebot also apply.

Summary

  • INP replaced FID as a Core Web Vital on 12 March 2024. FID measured only the input delay of the first interaction; INP measures the full latency of nearly every interaction.
  • A good INP is 200 ms or less at the 75th percentile. Poor is over 500 ms.
  • Each interaction has three phases: input delay, processing duration and presentation delay. Find which one is slow before choosing a fix.
  • Use field data with attribution to find the slow elements, then profile them in DevTools with CPU throttling.
  • Give visual feedback first, yield to the main thread, then do the heavy work.
SharePostLinkedInFacebook

Get Your SEO Audit

Every issue in this article, checked on your site by an auditor and delivered as a prioritized roadmap within 48-72 hours.

See pricing

Related articles