On this page
A filter button can feel broken even when the page loaded quickly. Interaction to Next Paint, or INP, measures responsiveness throughout a visit rather than only during startup. Improving it means finding the work that prevents visible feedback after an interaction, not simply making a Lighthouse score greener.
Understand what INP actually measures
INP observes qualifying click, tap, and keyboard interactions and reports a representative near-worst interaction latency for a visit, with allowances for outliers on longer sessions. A good experience targets 200 milliseconds or less at the 75th percentile, assessed separately for mobile and desktop. Consult the INP definition before comparing dashboards with different populations.
An interaction contains input delay, processing time, and presentation delay. The first is time waiting for handlers to run; the second covers handler execution; the third includes work needed before the next frame appears. Each component calls for a different fix.
Use the API latency tester to check a public endpoint involved in a slow filter or search. Treat that measurement as supporting evidence, not an INP test. An asynchronous request may finish long after an initial paint, so network latency and interaction latency must be investigated separately. Never paste production credentials into a diagnostic tool.
Collect field evidence before profiling
Start with Search Console or Chrome UX Report data to identify affected URL groups. Those datasets describe real visits, but a group-level warning does not identify the exact button responsible. Add privacy-conscious real-user monitoring that records the route template, interaction type, device class, and metric value without capturing typed text or personal data.
Use the web-vitals library for metric collection instead of inventing your own approximation. Its attribution build can help explain slow interactions. Sample deliberately, document consent requirements, and avoid sending full URLs when query strings might contain sensitive information.
Build a reproduction matrix around the most common reported actions: opening navigation, changing sorting, entering a search query, or dismissing a dialog. Include visits after several minutes, when background polling and accumulated DOM nodes can change behavior. A clean reload alone is insufficient.
Record a browser performance trace while performing one reproducible action. Use realistic CPU throttling for diagnosis, but do not compare a throttled lab result directly with an aggregated field percentile. Keep viewport, dataset size, and account state consistent between recordings. Preserve the original trace so improvements can be checked against actual evidence rather than memory.
Separate waiting, handlers, and rendering
If the input arrives during an unrelated long task, rewriting the click handler may achieve nothing. Look immediately before the event in the trace. Analytics callbacks, synchronous storage reads, and large background updates can all occupy the main thread. Give urgent work room to start by splitting noncritical work into smaller tasks.
For expensive handlers, provide immediate feedback before doing optional computation. The following pattern schedules nonessential work in a later task, using a fallback where the scheduling API is unavailable:
async function yieldToBrowser() {
if (globalThis.scheduler?.yield) {
await globalThis.scheduler.yield();
} else {
await new Promise(resolve => setTimeout(resolve, 0));
}
}
button.addEventListener("click", async () => {
status.textContent = "Updating results…";
button.disabled = true;
try {
await yieldToBrowser();
await updateResults();
} finally {
button.disabled = false;
}
});Yielding creates an opportunity for rendering; it is not a guarantee that every browser paints at that exact point. Nor does moving a huge synchronous calculation into another task make it inexpensive. Break calculations into chunks or move suitable pure computation to a worker.
Inspect presentation delay when handlers are short but feedback still arrives late. A single state change can trigger widespread style recalculation, layout, or painting. Check how many elements change, whether geometry is repeatedly read after writes, and whether framework updates touch unrelated regions.
Fix the interaction, not just the metric
A search interface should echo typing immediately while treating remote results as a separate state. Debounce network requests when appropriate, cancel outdated requests, and prevent stale responses from replacing newer results. Do not debounce the visible input value itself merely to reduce render frequency.
For large result sets, start by limiting displayed items and avoiding expensive per-row calculations. Consider virtualization when the size justifies its keyboard-navigation, focus, and browser-find tradeoffs. A faster list that loses a focused item is not a successful improvement. Related development guides can help evaluate implementation choices without turning the performance investigation into a framework migration.
Avoid disguising completion as responsiveness. A spinner appearing promptly is useful, but users still need accurate progress and reliable outcomes. Track task completion time alongside INP for operations such as submitting a form or applying several filters.
Review interaction effects separately from decorative polish. The guidance on micro-interactions is useful when deciding which visual feedback communicates state. Keep feedback local and lightweight; a full-page animation after every click can create more work than it explains.
Verify gains across realistic visits
Repeat the same action before and after the change with the same test data. Compare the trace phases rather than only total duration. If processing falls but presentation grows, the work may simply have moved. Check that another interaction, such as closing the panel, has not inherited the cost.
Use the browser long-task guidance to distinguish chunking from arbitrary delays. Adding a timer around everything can make controls feel inconsistent and leave race conditions untreated. Prefer explicit work boundaries that match user-visible steps.
Ship behind a controlled rollout when the change affects core navigation or checkout. Compare matching route and device cohorts, and wait for enough field observations before declaring success. A low-traffic page may not provide a stable percentile quickly; document that uncertainty instead of manufacturing precision.
Add a small regression checklist to the feature: expected feedback state, largest supported dataset, slow-device recording, and completion behavior during failure. Assign an owner to investigate a renewed slowdown. Responsiveness is a budget shared by every feature running on the page, including code introduced after the original optimization.
Key takeaways
- Measure real interactions, not just startup performance.
- Diagnose input delay, processing, and presentation separately.
- Show useful feedback without hiding slow completion.
- Retest large datasets, long visits, and slower devices.
- Confirm improvements in field data after rollout.
Reach designers & developers at work
Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.
Become a sponsor