Back to Performance
Performance
medium
mid

How would you improve Interaction to Next Paint (INP) on a page?

INP measures the worst end-to-end latency from any user interaction to the next paint. Improvements: split long tasks (`< 50ms`), defer non-urgent work (`requestIdleCallback`, React 18 `startTransition`), debounce/throttle handlers, offload to Web Workers, virtualize long lists, avoid layout thrash, and reduce hydration cost (RSC, partial hydration). p75 INP < 200ms is good.

5 min read·~10 min to think through

INP replaced FID in 2024 as a Core Web Vital. It measures the worst interaction latency in a session — from input to next paint. Hitting p75 < 200ms is the goal; > 500ms is poor.

What contributes to INP

  1. Input delay — main thread busy, can't handle the event.
  2. Processing time — your handler runs (state update, network call, etc.).
  3. Presentation delay — rendering + paint after the handler.

Levers

1. Break up long tasks

The main thread should never block > 50ms.

js
async function processBatch(items) {
  for (let i = 0; i < items.length; i += 100) {
    doWork(items.slice(i, i + 100));
    await new Promise((r) => setTimeout(r));  // yield
  }
}

Or scheduler.yield() (newer API).

2. Defer non-urgent updates (React 18)

jsx
const [filter, setFilter] = useState("");
const [list, setList] = useState(...);

function onChange(e) {
  setFilter(e.target.value);                  // urgent
  startTransition(() => setList(filterList(...)));  // non-urgent
}

The input updates immediately; the heavy filter is interruptible.

3. useDeferredValue for derived state

jsx
const deferredQuery = useDeferredValue(query);
const results = useMemo(() => search(deferredQuery), [deferredQuery]);

4. Debounce / throttle

For high-frequency events (scroll, resize, type-ahead), don't run heavy work per event. Debounce keyup; throttle scroll.

5. Web Workers

Move expensive compute (parsing big JSON, image processing, search indexing) off the main thread. Comlink makes this ergonomic.

6. Virtualize long lists

10k DOM nodes = guaranteed jank. TanStack Virtual or react-window keep only visible rows.

7. Avoid layout thrash

Reading layout properties (offsetWidth, getBoundingClientRect) after writes forces sync layout. Batch reads then writes.

8. Reduce hydration cost

  • React Server Components ship less JS.
  • Partial hydration (use client only where needed).
  • Islands architecture (Astro, Qwik).

9. CSS containment

contain: layout style paint on isolated UI sections cuts the layout/paint scope.

10. Measure

js
import { onINP } from "web-vitals";
onINP(({ value }) => sendToAnalytics({ name: "INP", value }));

Use Chrome DevTools Performance panel + Lighthouse + RUM for p75 in prod.

Interview framing

"INP is the worst interaction-to-paint latency in a session — target p75 < 200ms. Most wins: break long tasks (< 50ms each), use React 18 transitions / useDeferredValue for non-urgent updates, debounce hot handlers, virtualize lists, move heavy compute to a Worker, and reduce hydration JS via RSC. CSS containment scopes layout work. Always measure via web-vitals in production — synthetic tests miss the real distribution."

Follow-up questions

  • Compare INP vs FID.
  • How does startTransition help?
  • When would you reach for a Web Worker?

Common mistakes

  • Doing heavy work synchronously in event handlers.
  • Not virtualizing long lists.
  • Layout thrash from interleaved read/write.
  • No real-user monitoring — only lab tests.

Performance considerations

  • INP is dominated by main-thread work. Every ms shaved off the longest handler helps. RSC + partial hydration give multi-second wins on hydration-heavy apps.

Edge cases

  • Long input chains (paste 10k chars).
  • Janky devices (low-end Android).
  • Frame budget under battery-saver mode.

Real-world examples

  • Web.dev INP case studies, Next.js partial prerendering, Qwik resumability.

Senior engineer discussion

Seniors instrument p75 in prod, focus on the worst few interactions, and choose between code-level fixes (transitions, debounce) and architectural changes (RSC, workers, virtualization).

Related questions