INP: the metric that finally measures how your site feels
First Input Delay was easy to game—most sites passed while still feeling sluggish. Interaction to Next Paint (INP) replaced it because it measures the thing users actually experience: you tap, and how long until the screen visibly responds? Every interaction on the page counts, and roughly the worst one becomes your score.
The target is 200ms. Beyond that, humans stop perceiving cause and effect—the interface stops feeling like a tool and starts feeling like a request form.
Where INP debt hides
The classic offender is doing everything synchronously inside the event handler: update state, recompute, re-render, fire analytics, all before the browser is allowed to paint. The fix is a mindset: paint first, work later.
// ❌ Everything before paint
button.addEventListener('click', () => {
updateCart(); recalcTotals(); trackEvent();
});
// ✅ Paint the feedback, then do the work
button.addEventListener('click', () => {
button.classList.add('is-added');
requestAnimationFrame(() =>
setTimeout(() => { updateCart(); recalcTotals(); trackEvent(); })
);
});“Users do not experience your average. They remember the one tap that did nothing.”
The long-task diet
Any task over 50ms blocks every interaction that arrives during it. Break large loops with scheduler.yield() so the browser can interleave input handling. Hydration is the silent killer on framework sites—a user who taps during a 800ms hydration pass eats that entire delay. Islands, lazy hydration, or server components are INP fixes as much as architecture choices.
Measure with real-user data, not just the lab: the field panel in PageSpeed Insights, or a five-line PerformanceObserver for the event entry type. Find the worst interaction, fix it, repeat. INP optimisation is whack-a-mole where every mole you hit is something a real user hated.