
Core Web Vitals 2025: Why INP Replaced FID as a Google Ranking Factor (And How to Optimise for It)
INP replaced FID as a Core Web Vital in March 2024. Learn why redBus saw 7% sales increase from INP optimisation and how to achieve sub-200ms speeds.
Your site scored perfectly on First Input Delay. Then on 12 March 2024, Google replaced FID with Interaction to Next Paint (INP) as an official Core Web Vital. Your scores tanked.
redBus optimised their INP and saw a 7% sales increase. That's direct revenue impact from a technical metric most businesses haven't heard of. SpeedCurve's research shows conversion rates are roughly 10% higher at 100ms vs. 250ms INP on mobile.
INP measures how quickly your site responds throughout the entire visit, not just the first click. Every button press, every form interaction, every dropdown open. If your JavaScript is blocking the main thread, users sit there clicking and nothing happens. They bounce. You lose conversions.
Google's threshold is 200 milliseconds for "good" INP. Anything over 500ms is poor. But Google's documentation quietly acknowledges: 100ms is where responsiveness actually feels instant. That's your real target.
What Changed and Why FID Wasn't Good Enough
First Input Delay measured one thing: the delay between a user's first interaction and when the browser could actually respond. That's it. Just the first click or keypress on page load.
The problem: Your site could have perfect FID but terrible responsiveness after the initial interaction. Maybe your first click responds instantly, but every subsequent click takes 800ms because your JavaScript framework is churning through unnecessary re-renders. FID wouldn't catch this.
INP measures every interaction across the entire page visit. It reports the 75th percentile response time—meaning 75% of your users experience that speed or better, 25% experience worse.
From Google's official web.dev documentation:
"Interaction to Next Paint (INP) is a Core Web Vital metric that assesses a page's overall responsiveness to user interactions by observing the latency of all qualifying interactions that occur throughout the lifespan of a user's visit to a page."
Translation: INP catches the slow interactions FID missed. It's a better metric for actual user experience.
The Timeline
- May 2023: Google announces INP as "pending" Core Web Vital
- 12 March 2024: INP officially replaces FID as a Core Web Vital
- 2025: INP remains one of three Core Web Vitals alongside LCP and CLS
As of right now, your Core Web Vitals are:
- LCP (Largest Contentful Paint) - How fast your main content loads
- INP (Interaction to Next Paint) - How fast your site responds to interactions
- CLS (Cumulative Layout Shift) - How stable your layout is
These directly influence your search rankings. Not massively—content relevance still dominates. But INP acts as a tiebreaker when Google chooses between similar pages. Poor INP can also disqualify you from Featured Snippets.
What 200ms Actually Means (And Why You Need 100ms)
Good INP: Less than 200 milliseconds Poor INP: Over 500 milliseconds
These thresholds measure the complete interaction cycle:
- Input delay (waiting for main thread to be free)
- Event handler processing (running your JavaScript)
- Rendering (browser paints the visual update)
Google measures this at the 75th percentile of all interactions during a page visit. If a user has 20 interactions, INP is the 15th slowest one. This methodology captures typical experience whilst accounting for outliers.
Whilst 200ms is Google's "good" threshold for ranking purposes, research consistently shows 100ms is where responsiveness feels truly instant to users. Between 100–300ms, interactions feel sluggish. Above 300ms, users perceive the site as broken.
SpeedCurve's data backs this up: conversion rates are roughly 10% higher at 100ms vs. 250ms on mobile devices. Both scores qualify as "good" by Google's standards, but the business impact differs significantly.
Aim for sub-200ms to pass Google's test. But push for sub-100ms if you care about actual conversion rates.
Why Your INP Is Probably Bad
Mobile INP is typically 2-3x worse than desktop. Slower processors, less memory, unreliable network connections. If your desktop INP is 150ms, your mobile INP might be 400ms—failing Google's threshold.
The culprit? JavaScript long tasks blocking the main thread.
What's a Long Task?
Any JavaScript execution over 50 milliseconds is a "long task." While your JavaScript runs, the browser can't respond to user input. The user clicks a button. Nothing happens. They click again. Still nothing. Your code is blocking them.
Common sources of long tasks:
- Heavy framework rendering (React, Vue, Angular re-rendering entire component trees)
- Third-party scripts (analytics, ads, chat widgets)
- Unoptimised event handlers (running synchronous, blocking code on every click)
- Large JavaScript bundles (browser parsing/compiling megabytes of code)
- Complex state management (Redux/Vuex triggering cascading updates)
That 800ms lag when users click your dropdown menu? Probably a long task blocking the main thread. The slow form submission? Long task. The laggy image carousel? Long task.
Real Example: Analytics Ruining INP
A common pattern: sites with INP around 420ms failing Google's threshold, traced to analytics implementation.
Every interaction triggers analytics events that run synchronously on the main thread. Click a button → block main thread for 80ms whilst analytics fires. Open a dropdown → another 60ms blocked. The analytics create long tasks on every single interaction.
The fix documented in this case study: implement yielding to the main thread between analytics operations. Break up the work into smaller chunks, letting the browser respond to users between analytics calls.
Result: 19% INP improvement. Not radical restructuring—just smarter task scheduling.
How to Actually Measure INP
Don't guess. Measure real user data first.
Field Data (Real Users)
Google Search Console - Core Web Vitals report
- Shows actual INP experienced by your users
- Data from Chrome User Experience Report (CrUX)
- Segmented by mobile/desktop
- Updates weekly with 28-day rolling window
PageSpeed Insights - https://pagespeed.web.dev/
- Field data (CrUX) + lab data (Lighthouse) for any URL
- Identifies which interactions are slowest
- Provides specific recommendations
Chrome DevTools - Performance panel
- Record your own session
- See exact INP values for interactions you perform
- Identify long tasks in the flame chart (look for yellow blocks over 50ms)
Field data tells you what real users experience. This is what Google uses for rankings. If your field data says INP is 450ms, that's your problem regardless of what lab tests show.
Lab Data (Synthetic Testing)
Lighthouse (built into Chrome DevTools)
- Simulates interactions under controlled conditions
- Uses Total Blocking Time (TBT) as proxy for INP
- Good for catching regressions before real users see them
WebPageTest - https://www.webpagetest.org/
- Test from different locations and devices
- Throttle network/CPU to simulate mobile
- Detailed waterfall showing exactly what's blocking the main thread
Lab data lets you debug issues in controlled environments. But it's synthetic—real user patterns matter more.
Optimisation Techniques That Actually Work
These aren't theoretical. These are proven techniques with measurable INP improvements across industry case studies.
1. Yield to the Main Thread (19% Improvement)
The concept: break up long tasks by briefly pausing to let the browser respond to user input.
Before (one long task blocking main thread for 500ms):
function processLargeDataset(data) {
for (let i = 0; i < data.length; i++) {
// Heavy processing
processItem(data[i]);
}
}
After (yielding every 50 items):
async function processLargeDataset(data) {
for (let i = 0; i < data.length; i++) {
if (i % 50 === 0) {
// Yield to main thread
await new Promise(resolve => setTimeout(resolve, 0));
}
processItem(data[i]);
}
}
This splits one 500ms task into multiple sub-50ms tasks. Between tasks, the browser can respond to user clicks and key presses.
Target: Keep individual tasks under 50ms. Google's official guidance from web.dev recommends this as the deadline for yielding.
Real result: The analytics optimisation mentioned earlier achieved 19% INP improvement just by yielding properly.
2. Optimise React Rendering (45% Improvement)
React apps are notorious for poor INP because unnecessary re-renders block the main thread.
Common React INP killers:
- Complex
useEffectdependencies causing render loops - Large state objects triggering full component tree re-renders
- No memoisation of expensive calculations
- Poor Redux/Zustand selector implementation
Fixes that work:
// Memoize expensive components
const ExpensiveComponent = React.memo(({ data }) => {
return <div>{/* Complex render */}</div>;
});
// Memoize expensive calculations
const computedValue = useMemo(() => {
return expensiveCalculation(data);
}, [data]);
// Use React 18+ transitions for non-urgent updates
import { startTransition } from 'react';
startTransition(() => {
setSearchResults(newResults);
});
Breaking down complex custom hooks into smaller ones with specific dependencies also helps. Instead of one massive hook with 12 dependencies that triggers on any change, split it into focused hooks that only re-run when their specific dependencies change.
Case study from performance experts: React app with poor INP implemented these patterns—breaking down hooks, improving Redux selectors, replacing React Router APIs with window.location where possible.
Result: 45% INP improvement.
3. Defer Third-Party Scripts
Analytics, ads, chat widgets, A/B testing tools—they all run JavaScript that blocks your main thread.
Strategy: Load them after your core interactions are responsive.
// Wait until page is interactive
if (document.readyState === 'complete') {
loadThirdPartyScripts();
} else {
window.addEventListener('load', loadThirdPartyScripts);
}
// Or use Idle Until Urgent pattern
requestIdleCallback(() => {
loadAnalytics();
loadChatWidget();
}, { timeout: 2000 });
Your conversion funnel shouldn't wait for Hotjar to initialise. Load it after critical interactions work smoothly.
4. Code Splitting & Lazy Loading
Stop shipping one massive JavaScript bundle. Split code by route and load it on-demand.
Next.js example:
// Static import (loads everything upfront)
import HeavyComponent from './HeavyComponent';
// Dynamic import (loads only when needed)
const HeavyComponent = dynamic(() => import('./HeavyComponent'));
Impact: Less JavaScript to parse/compile on initial load means faster Time to Interactive and better INP scores. Smaller bundles = less main thread blocking.
5. Web Workers for Heavy Computation
Offload expensive processing to a background thread so the main thread stays responsive.
Use cases:
- Client-side search/filtering
- Data parsing and transformation
- Complex calculations
- Image processing
Example:
// worker.js
self.addEventListener('message', (e) => {
const result = expensiveCalculation(e.data);
self.postMessage(result);
});
// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.addEventListener('message', (e) => {
updateUI(e.data);
});
Google case study cited across performance documentation: splitting work between UI and worker threads improved INP by 35%.
6. Debounce & Throttle Event Handlers
Stop running expensive operations on every single keypress, scroll event, or window resize.
// Debounce: Wait until user stops typing
const debouncedSearch = debounce((query) => {
performSearch(query);
}, 300);
// Throttle: Execute at most once per interval
const throttledScroll = throttle(() => {
updateScrollPosition();
}, 100);
Your search-as-you-type doesn't need to query the API on every keystroke. Debounce it. Your scroll handler doesn't need to fire 60 times per second. Throttle it.
Mobile-Specific Optimisation
Remember: mobile INP is usually 2-3x worse than desktop. These fixes specifically target mobile devices.
Passive Event Listeners
By default, touch event listeners block scrolling whilst they execute. Make them passive to allow scrolling:
// Blocks scrolling
element.addEventListener('touchstart', handler);
// Doesn't block scrolling
element.addEventListener('touchstart', handler, { passive: true });
Larger Touch Targets
WCAG 2.2 requires 44×44 CSS pixel touch targets. This isn't just accessibility—smaller targets cause mis-taps, triggering unintended interactions and degrading INP scores.
Check your mobile navigation. If you've got 28px icon buttons crammed together, users are mis-tapping and your INP suffers.
Reduce JavaScript on Mobile
Serve less JavaScript to mobile devices. Use responsive imports:
if (window.innerWidth > 768) {
import('./desktopFeatures.js');
} else {
import('./mobileFeatures.js');
}
Mobile devices don't need your desktop features. Strip them out.
The redBus Case Study: 7% Sales Increase
redBus, one of India's leading bus ticket booking platforms, faced poor mobile responsiveness affecting conversions.
They implemented comprehensive INP optimisation:
- JavaScript performance improvements
- Main thread yielding for heavy operations
- Third-party script deferral
- React rendering optimisation
Result: INP improved to sub-200ms. Sales increased 7%.
For a high-traffic e-commerce platform, 7% sales growth from technical optimisation alone is massive. That's the business case for caring about INP.
Measuring Success
Track these metrics before and after INP optimisation:
Technical Metrics:
- INP score (field data from Google Search Console)
- 75th percentile interaction latency
- Number of long tasks per page
- Total Blocking Time (TBT) in Lighthouse
Business Metrics:
- Conversion rate (primary KPI)
- Bounce rate
- Pages per session
- Mobile vs. desktop conversion gap
Set up Real User Monitoring (RUM) to track INP continuously. If a deploy regresses INP, you'll know before it tanks your conversion rates.
What This Means for Your Development Process
At Numen Technology, Core Web Vitals are built in from the start:
- Code splitting by default in Next.js apps
- Lazy loading for non-critical components
- Performance budgets in CI/CD (builds fail if INP regresses)
- Regular profiling during development, not just at the end
Ongoing support includes continuous monitoring. INP can degrade as you add features, update dependencies, or integrate third-party tools. Catch regressions before they affect rankings or conversions.
We built GuardianScan to monitor exactly this: all three Core Web Vitals (LCP, INP, CLS) alongside 47 other performance checks. It runs 50 checks in about 45 seconds and alerts when INP starts creeping above 200ms.
Start With the Biggest Problems
You don't need to optimise everything. Focus on:
- High-traffic pages (homepage, product pages, checkout)
- Interaction-heavy pages (forms, configurators, search)
- Mobile experience (where INP is typically worst)
Run Chrome DevTools Performance profiler on these pages. Look for yellow blocks over 50ms in the flame chart. Those are your long tasks. Click on them to see exactly which JavaScript is blocking the main thread.
Fix the longest tasks first. A single 800ms task has more impact than eight 50ms tasks.
The 200ms Target Isn't Optional
Google changed from FID to INP because FID didn't correlate with real user experience. INP does. Poor INP means users perceive your site as slow and unresponsive—even if your page load times are fast.
redBus proved the business impact: 7% sales increase from INP optimisation. SpeedCurve's data shows 10% higher conversion rates at 100ms vs. 250ms. Both scores pass Google's test, but one converts significantly better.
If you're struggling with poor INP scores or want to understand where your site stands, book a strategy session. We'll run Core Web Vitals analysis, identify your biggest bottlenecks, and show you exactly what needs fixing.