Skip to content
// Technical · 14 min

Core Web Vitals: INP for the modern stack

INP replaced FID in 2024. How to diagnose and fix it on React, Vue and SSR stacks, with the exact DevTools workflow that gets fixes shipped in a sprint.

March 8, 2026 · by SEO Legendary Engineering

1. What changed when INP replaced FID

First Input Delay measured one thing: the delay before the browser began processing the first interaction. Interaction to Next Paint measures every interaction across the full page lifetime, then reports the 98th percentile. It's harder to game and closer to what users feel.

2. Diagnosing INP in 20 minutes

  1. 01Open the PageSpeed Insights report, INP is measured from field data (CrUX), so the number reflects real users.
  2. 02Open Chrome DevTools → Performance panel → "Interactions" track. Record while interacting with the top-3 user paths.
  3. 03Look for interactions with a red block on the Interactions track. That's your problem child.
  4. 04Zoom into the block; find the long task. It's almost always a synchronous handler, hydration burst, or unbatched state update.

3. React: the four INP killers

  • Uncontrolled re-renders after input change, wrap child components in memo or lift state closer to where it's used.
  • Heavy work in onChange / onClick handlers, defer to requestIdleCallback or wrap non-urgent updates in startTransition.
  • Hydration mismatches that trigger full-tree re-render, server and client output must match exactly.
  • Third-party scripts (chat widgets, tag managers) that hijack the main thread on first click.
// React 18 pattern
import { startTransition, useState } from "react"; function Search() { const [input, setInput] = useState(""); const [results, setResults] = useState<Result[]>([]); const onChange = (v: string) => { setInput(v); // urgent, keeps the input responsive startTransition(() => { setResults(compute(v)); // deferred, INP-friendly }); }; return <input value={input} onChange={(e) => onChange(e.target.value)} />; }

4. SSR frameworks and the hydration cost

Next.js, Remix and TanStack Start ship JavaScript that must hydrate before the page becomes interactive. Two techniques reliably move the needle:

  • Selective hydration, only hydrate what's above the fold on first paint. Islands architecture is the extreme version.
  • Streaming server rendering, flush HTML as soon as it's ready, hydrate incrementally as chunks arrive.

5. The third-party tax

The most reliable single-day INP win is not code, it's audit and cull. Intercom, Segment, HubSpot, Hotjar, ad pixels: each one is a long-task machine. Load them on interaction rather than on document ready.

// delayed loader
// Load chat widget only after the user proves they want it const idle = window.requestIdleCallback ?? ((cb: () => void) => setTimeout(cb, 2000)); idle(() => { const s = document.createElement("script"); s.src = "https://widget.intercom.io/widget/APP_ID"; s.async = true; document.body.appendChild(s); });

6. A one-sprint fix plan

DayTaskExpected INP impact
MonBaseline CrUX + Performance recordings on top-3 paths0ms, you're measuring
TueWrap non-urgent setState in startTransition-30 to -80ms
WedDefer or cull 2 third-party scripts-60 to -150ms
ThuSelective hydration or component memoization pass-40 to -100ms
FriShip, re-measure with WebVitals JS in productionconfirms field data
// key takeaways
  • ✓INP measures the 98th percentile of every interaction, much harder to fake than FID.
  • ✓In React, startTransition is the single highest-leverage change.
  • ✓SSR frameworks pay a hydration tax; selective hydration is the answer.
  • ✓The fastest single-day win is culling or deferring third-party scripts.
// want this shipped on your site?

Turn this playbook into a 90-day roadmap.