Here's a situation that comes up a lot. A business launches a new website and it aces every speed test. The page appears almost instantly. Yet staff keep saying it "feels sluggish", and on mobile the quote form converts worse than it did on the old, supposedly slower site.
In cases like this the speed tests are usually measuring the wrong thing. The page loads fast. Everything after that is slow: tapping the menu, picking an option in the form, pressing "Next". Each tap comes with a pause before the screen changes, and on a mid-range phone those pauses can stretch to half a second or more.
Meet INP
In March 2024 Google replaced First Input Delay with Interaction to Next Paint (INP) as a Core Web Vital, and INP has turned out to be the one sites struggle with most. It watches every click, tap and key press during a visit and measures how long each takes to produce a visible response. The score reflects roughly the worst of those, so one slow button can drag down the whole page.
The thresholds are simple. 200 milliseconds or less is good, over 500 is poor, and anything in between needs work. Like the other Core Web Vitals, INP is judged at the 75th percentile of real visits. The benchmark isn't your fast office laptop. It's a customer on a three-year-old phone on a train.
Commercially, it matters for two reasons. Core Web Vitals feed into search ranking, and a site that hesitates when you touch it feels broken. Nobody consciously notices a 400ms delay, but people trust the site a little less and leave a little sooner.
Why modern sites suffer
The browser has one main thread that does nearly everything: running JavaScript, calculating styles and layout, and painting pixels. When someone taps a button, the browser has to finish what it's doing on that thread, run your event handler and only then paint the result. If the thread is busy, the tap waits.
Modern sites keep that thread very busy. Third-party scripts are the usual first suspect. Analytics, tag managers, chat widgets, A/B testing tools and ad scripts all do their own work on the same thread, often at unpredictable moments.
Hydration is another. Frameworks that render HTML on the server and then "wake it up" in the browser can tie up the main thread for a while after the page looks ready, so it appears interactive before it is.
Then there are heavy event handlers, like a click that re-renders a big component tree, filters a long list or recalculates a form before the browser gets a chance to paint. And huge DOMs, where thousands of elements make every style and layout recalculation more expensive.
Finding the slow interactions
Lab tools are a starting point, but INP is really a field metric, because it depends on what real people click. Start with field data. Search Console's Core Web Vitals report and the Chrome UX Report will tell you whether you have a problem and on which groups of pages.
To find out which interactions are slow, you need real-user monitoring that records the element and interaction behind each poor INP. The open-source web-vitals library can send that attribution data to your analytics with a few lines of code. Once you know it's "the filter dropdown on the product listing page, on Android", fixing it is an engineering job rather than guesswork.
Then reproduce it locally. Open the browser's performance panel, throttle the CPU to mimic a slower device, record the interaction and look for long tasks, meaning chunks of main-thread work over 50ms sitting between the tap and the paint.
Fixes that work
Paint first, work second
The most effective pattern is to show the user something straight away (a pressed state, a spinner, the new tab highlighted) and do the expensive work afterwards. Split long event handlers so the visual update happens first and the heavy lifting waits until the browser has painted. Yielding to the main thread between chunks of work lets the browser respond to the user in the gaps.
Put third-party scripts on a diet
Go through every third-party script on the page and ask whether anyone still uses what it does. Most sites have at least one tag nobody can explain. Load the ones you keep after the page is interactive, and only on the pages that need them.
Ship less JavaScript
Every kilobyte of JavaScript has to be parsed and run on that same main thread. Server components, islands architecture and partial hydration all exist to cut how much code runs in the browser. Parts of the page that never change after load shouldn't need JavaScript at all.
Keep the DOM lean
Virtualise long lists so only the visible rows exist in the DOM. Don't render big hidden sections, like every tab's content or every step of a form, until someone needs them.
Usually it's unglamorous
In a case like the quote form above, the fixes are rarely dramatic. Defer the chat widget until after the first interaction, clean out the tag manager container, and have the form update the screen before it runs validation. Nobody would notice any one of those changes, but together they can move mobile INP from "poor" to "good", and the site starts responding when people touch it.
If your site aces the speed tests but still feels slow, we can instrument it, find the interactions that are hurting you and fix them.

