Engineering
Getting Ahead of INP Before March
There is a deadline hiding in plain sight for every team that cares about Core Web Vitals: in March 2024, Interaction to Next Paint replaces First Input Delay as the responsiveness metric. Google announced the timeline back in May, and it has spent 2023 as a pending item on everyone's list. We spent the last two months running INP remediation across our client portfolio, and the headline finding is uncomfortable: sites that pass FID with perfect scores routinely fail INP. If your team is planning to look at this in Q1, you are planning to look at it late.
Why FID was easy and INP is not
FID measured one thing: the delay before the browser could begin handling your very first interaction. Modern frameworks made passing it nearly automatic, which is exactly why it is being retired. It graded the handshake, not the conversation.
INP measures the slowest meaningful interaction across the entire page lifetime, from input to the next paint. Every click, every keypress, all session long, and your score is effectively the worst of them. That single change moves the problem from "how fast does the page boot" to "how heavy is your event handling everywhere," which is a much more honest question and a much harder one. All the sins FID never saw are suddenly visible: the filter panel that re-renders the world, the cart button that runs analytics synchronously before responding, the autocomplete that does layout work on every keystroke.
What actually moved the number
Across our remediations this fall, nearly all the wins came from four patterns:
- Yield inside long handlers. The single most effective fix. Do the minimal visual acknowledgment first, then yield to the main thread and finish the work afterward.
- Get analytics and third parties out of the interaction path. Tag managers were implicated in every single audit we ran, no exceptions. Defer, batch, and move what you can off the critical path.
- Stop rendering what did not change. On React builds, interaction-triggered re-renders of huge trees were the top framework-level cause. Memoization, list virtualization, and moving state down fixed most of it.
- CSS containment for complex regions, which limits how much layout work one interaction can trigger.
async function onFilterChange(next: FilterState) {
setPending(true); // paint feedback immediately
await new Promise((r) => setTimeout(r, 0)); // yield to main thread
applyFilters(next); // heavy work after the paint
}
On Northwind's product listing page, the filter interaction went from roughly 500ms of blocked main thread to comfortably under the 200ms "good" threshold with two days of work, almost all of it the first two patterns. None of this is exotic engineering. It is housekeeping that FID never forced anyone to do.
How to run this at your team
Start with field data, not lab data: CrUX and your RUM tooling will tell you which real interactions are slow, and it is usually three or four specific ones per template, not a diffuse problem. Fix those, ignore the rest, re-measure in the field. Budget it like a small project, one to two weeks per major property, not a standing initiative.
And a note for the skeptics who ask whether any of this matters beyond the ranking checkbox: responsiveness is the web vital users can actually feel. LCP is about first impressions; INP is about whether the site feels broken every time they touch it, right through checkout. Google replacing FID is just the measurement catching up to the experience. March is the deadline, but the users were always the point.
Building something this could apply to?
We take on a small number of flagship projects each quarter.
Start a project