INP is the hard Core Web Vital, and it is a JavaScript problem
Interaction to Next Paint measures how long a page takes to visibly respond to a user interaction; the passing threshold is 200ms at the 75th percentile of real users. Unlike LCP, it is almost entirely a JavaScript-architecture problem - long tasks blocking the main thread - so it is fixed by breaking up work, deferring third-party scripts, and shipping less client JavaScript, not by compressing images.
Why this one is different
LCP and CLS respond to asset discipline: compress the hero image, preload the font, reserve space for anything injected. Teams get those into the good band with a focused week of work.
INP does not yield to that. It measures the delay between a user's interaction and the next visible paint, and that delay comes from the main thread being busy. You fix it by changing what your JavaScript does and when, which touches architecture rather than assets - which is why it is the vital most sites are still failing.
Where the long tasks come from
In our audits the same sources recur, roughly in this order.
- Third-party tags - analytics, chat widgets, tag managers, consent banners - executing on the interaction path
- Hydration of components that never needed to be interactive at all
- Event handlers doing synchronous work - a filter, a sort, a large state update - before yielding
- Layout thrash: reading a layout property, writing a style, reading again, inside one handler
- Large re-render cascades where one state change re-renders a subtree that did not change
The fixes, in order of payoff
Ship less client JavaScript. Server components and plain server-rendered HTML have no hydration cost and no INP contribution. On this site, every content page is server-rendered with effectively no client JavaScript, which is the cheapest INP win available.
Yield to the main thread inside handlers. Do the work that produces visible feedback, yield, then continue. A handler that yields after painting a response feels instant even when the total work is unchanged.
Move third parties off the interaction path - load them after interaction, or on idle. A tag that runs during a click is directly measured in your INP.
Batch layout reads and writes. Read everything, then write everything, never interleaved.
Measure the field, not the lab
Lighthouse cannot measure INP meaningfully, because there is no user interacting. Lab tools estimate; only field data is real.
Use the Core Web Vitals report in Search Console for the 28-day rolling window Google actually ranks on, and add real-user monitoring that attributes each slow interaction to a selector and a script. Without attribution you are guessing which handler is slow.
The rolling window also means you cannot validate a fix quickly. Expect three to four weeks before field data reflects a deploy - plan releases accordingly rather than re-tuning weekly on noise.
Treat it as a budget
The durable fix is process, not a one-off sprint. Set the budget - 200ms INP at p75, plus a client-bundle size ceiling - and fail the build when a change breaks it.
Performance work that is not enforced in the pipeline decays. Every team rediscovers this, usually about two quarters after the optimisation sprint that fixed everything.
Questions this raises
What is a good INP score?
200ms or less at the 75th percentile of real user interactions, measured over a 28-day window. Between 200ms and 500ms needs improvement; above 500ms is poor.
Does INP affect Google rankings?
Core Web Vitals are part of Google's page experience signals and act as a differentiator in competitive results. They do not outrank relevance or content quality - a fast page with commodity content still loses to a slower page that answers the question better.
Why did our INP get worse after adding a chat widget?
Because a third-party script executing during or near an interaction is measured as part of that interaction's delay. Load such widgets after first interaction or on idle, and confirm the change in field data rather than in a lab run.
Related
Idempotency is the whole job
Automation that cannot safely run twice is a liability. Idempotency keys, durable execution, and decline-code-aware retries - the patterns that keep automated money movement correct.
pgvector or a dedicated vector database
When PostgreSQL with pgvector is the right default for RAG, what actually breaks at scale, and the specific signals that justify moving to a dedicated vector store.
Custom Software Engineering
Custom software engineering for teams that need sub-50ms responses, honest architecture, and code they can own. Next.js, Go, PostgreSQL and edge deployment, built by a software engineering studio in Kolkata, India.
Published 22 August 2026 · Last reviewed 22 August 2026 · Written by Manish Meena in Kolkata, India.
