Next.js · Core Web Vitals · Performance

Next.js site failing Core Web Vitals? How to fix it

Next.js site failing Core Web Vitals? It's usually scripts, hydration, hero images or fonts. Here's how to read the report and fix each one.

Mohit Goyal 11 min read
Next.js site failing Core Web Vitals? How to fix it

A Next.js site usually fails Core Web Vitals for one of four reasons: third-party scripts fighting for the main thread (which hurts INP), too much JavaScript to hydrate, a hero image that loads late or too big (which hurts LCP), or fonts and late-injected elements that push the layout around (which hurts CLS). Check which metric fails for real mobile visitors in PageSpeed Insights, match it to its usual culprit and fix that first. Most fixes are small, targeted changes to images, fonts, scripts or components. You rarely need a rebuild.

Part of my job as Senior Web Developer at Procol is keeping procol.ai, which I rebuilt on Next.js, and its landing pages fast on every device. Next.js gives you good tools for speed, but it can't stop anyone adding a chat widget, five tracking tags and an autoplay video to the homepage. What follows is the triage path I'd hand a business owner: what each metric means, how to read the report, what usually breaks and when it's time to pay someone. If your marketing pages run on WordPress or a headless setup, my guide to fixing Core Web Vitals on WordPress covers that side.

What do LCP, INP and CLS actually measure?

Core Web Vitals are three measurements of how a page feels to real visitors. LCP is about loading, INP is how quickly the page reacts when someone taps or clicks, and CLS is whether the layout stays put while it loads. Google's thresholds, from web.dev:

MetricWhat it measuresGoodPoor
LCP (Largest Contentful Paint)How long the main content takes to appear2.5 s or lessOver 4 s
INP (Interaction to Next Paint)How quickly the page responds to taps and clicks200 ms or lessOver 500 ms
CLS (Cumulative Layout Shift)How much the layout jumps while loading0.1 or lessOver 0.25

Two details trip people up. A page is judged at the 75th percentile of real page loads, measured separately for mobile and desktop, so your fast laptop on office Wi-Fi tells you very little. And INP replaced First Input Delay on 12 March 2024. It's a much stricter test. A Next.js site that passed in 2023 can fail today without anyone touching the code.

If you're failing, you've got plenty of company. In the 2025 Web Almanac, only 48% of mobile sites passed all three. Here's how mobile sites did on each one:

Mobile sites with a good score, 2025 Web Almanac
  • All three CWV48%
  • Good LCP62%
  • Good INP77%
  • Good CLS81%

LCP is the one most sites fail. INP is where phones and laptops split: the same report found 97% of desktop sites have good INP against 77% on phones. JavaScript-heavy React and Next.js sites tend to sit on the wrong side of that split.

How do I read my PageSpeed Insights report?

Start with the field data at the top of PageSpeed Insights. That section, built from real Chrome users over a 28-day rolling window, is the only part that decides whether you pass. The 0 to 100 performance score underneath comes from one simulated phone. It's handy for diagnosis, but it isn't your result, and a 95 can sit right next to a failing INP.

A standard Lighthouse page load can't measure INP, because nobody is tapping the page. web.dev notes that lab tests use Total Blocking Time as the stand-in. So if TBT is high in Lighthouse, treat it as your INP warning light.

Then open the Core Web Vitals report in Google Search Console. It groups similar URLs, which shows you whether the problem is one page or a whole template, like every blog post or every landing page.

  1. 1

    Check mobile field data

    In PageSpeed Insights, open the Mobile tab and note which of LCP, INP and CLS is failing for real users.

  2. 2

    Find the failing template

    Use the Core Web Vitals report in Search Console to see which group of URLs fails, so you fix a template rather than a single page.

  3. 3

    Read the matching diagnostics

    For LCP, find the LCP element. For CLS, find the layout shift culprits. For INP, look at Total Blocking Time and third-party code.

  4. 4

    Fix the biggest cause first

    Ship one change at a time so you know what worked, then re-run the lab test to confirm it.

  5. 5

    Wait for field data

    Field data is a 28-day rolling window of real visits, so the report turns green a few weeks after the fix, not the next morning.

If the diagnostics read like another language, paste the report into my free Page Speed Fix Planner. It tells you which vitals pass or fail and what's causing each one, ranks the fixes by impact and effort, and gives you the code or settings for your platform in plain English.

Which Next.js problem is behind my failing metric?

Each failing metric has a usual suspect on Next.js. For LCP it's the hero image or a slow server response. For CLS it's unsized media, fonts and banners. For INP it's third-party scripts and over-hydration. This is the map I start from:

Failing metricUsual Next.js culpritFirst thing to try
LCPHero image lazy-loaded, oversized or rendered client-sideMark the hero image as priority and size it correctly
LCPPage rendered on every request, slow server responseMake the page static or cached where content allows
CLSImages, embeds or banners without reserved spaceSet dimensions and reserve space for anything injected
CLSWeb fonts swapping lateLoad fonts through next/font
INPThird-party tags and widgetsDelay or remove them with next/script
INPWhole pages marked "use client"Push client components down to the interactive parts

Why is my Next.js LCP slow?

Usually it's the hero. Either the image is lazy-loaded, too big or waiting on JavaScript, or the server builds the page fresh on every request. The LCP element is normally the hero image or the main heading, so look there first:

  • The hero image is lazy-loaded. The Next.js Image component lazy-loads by default. That's right for images below the fold and wrong for the hero. Mark the hero image as priority (the prop name depends on your Next.js version) so the browser fetches it straight away.
  • The image is too big. A missing or wrong sizes value can send a desktop-width image to a phone. Compress source images before they go into the CMS. Under1MB, my free in-browser compressor, does it without uploading anything.
  • The hero waits for JavaScript. Carousels, animated headlines and content fetched in the browser only show up once the JavaScript has run. Render the first slide or heading on the server.
  • The server is slow to respond. If a page reads cookies or makes an uncached data request, Next.js may render it fresh on every visit. Marketing pages rarely need that, and static generation or timed revalidation usually sorts it. Hosting region matters too, so check where your pages are served from compared with where your visitors are.

What causes layout shift on a Next.js site?

Four things, mostly: media without dimensions, fonts swapping late, banners injected at the top, and content that changes after hydration. In my experience CLS is the easiest of the three to fix once you've spotted the element that moves.

  • Media without dimensions. The Next.js Image component needs a width and height, or a sized container, so it can reserve space. Raw image tags, YouTube embeds and iframes coming from CMS rich text often don't have them.
  • Fonts swapping late. When a custom font arrives after the fallback, the text reflows. Vercel's write-up on next/font explains how it self-hosts fonts and cuts the shift caused by font loading. If the site still links Google Fonts in the head, switch to next/font.
  • Banners injected at the top. Cookie bars, promo strips and announcement bars that appear after load shove everything down. Reserve their space, or show them as an overlay at the bottom.
  • Content that changes after hydration. If a component renders one layout on the server and another in the browser (based on screen width, saved settings or location), the page jumps. Handle responsive layout in CSS, not JavaScript.

Why is INP poor on my Next.js site?

It's rarely the framework's fault. Poor INP almost always traces back to third-party scripts, too much client-side hydration or heavy event handlers. This is where Next.js marketing sites fail most often, because every tap has to wait for whatever JavaScript is already busy.

  • Third-party scripts. Tag Manager containers with years of old tags, chat widgets, heatmaps and A/B testing tools all compete with your own code. The Next.js Script component lets you choose when each one loads: afterInteractive is the default, lazyOnload waits for browser idle time, and worker moves a script off the main thread. worker is still experimental and currently works only with the Pages Router, not the App Router. Before any of that, delete the tags nobody uses.
  • Too much hydration. Put "use client" at the top of a layout and the whole page ends up in the browser bundle. Keep pages as server components and make only the interactive bits client components: the menu button, the form, the tabs. Load heavy widgets below the fold with next/dynamic.
  • Heavy event handlers. Mega menus, product filters and site search that re-render big lists on every keystroke block the next paint. Show feedback first, then do the heavy work.

Can I fix it myself or do I need a developer?

Some of it you can do yourself. Anything inside the Next.js code needs a developer. Your marketing team can remove unused tags in Tag Manager, drop the chat widget from pages where nobody uses it, swap an autoplay hero video for a still image and compress images before uploading them.

Image props, font loading, script strategies, rendering and caching choices, and moving client components back to the server all need someone in the code. Be wary of anyone who pitches a full rebuild before they've looked at the field data, or who promises a 100 Lighthouse score instead of passing Core Web Vitals for real users. Those are different goals.

How much does fixing Core Web Vitals on Next.js cost?

Market ranges run from about $200 to $500 for speed work on a simple site, $800 to $2,000 for small Next.js fix projects, and $1,200 to $3,500 a month for general ongoing Next.js maintenance. The spread is wide because the scope is:

Type of workTypical market rangeSource
Speed optimisation, simple custom or Next.js site$200 to $500Web Aloha
Small Next.js updates and fixes$800 to $2,000 per projectUpwork
Ongoing Next.js maintenance (general)$1,200 to $3,500 per monthUpwork

Upwork says its ranges are adapted from general web developer project pricing, so take them as a rough guide. What actually moves the price is which metric fails and how many templates it affects. Fixing LCP on one hero image is quick. An INP problem baked into the client-side architecture across the whole site means refactoring components and re-testing every form and menu. Access counts as well: a developer with the repo, the hosting dashboard and Tag Manager will move far faster than one working from screenshots.

What should I ask a developer before hiring?

You want to know what they'll fix, how they'll prove it and how they'll keep it fixed. These are the questions I'd ask:

  • Which metric and which URL group will you fix, and how will you prove it with field data?
  • Will tracking still work afterwards? Marketing needs GA4, ads pixels and forms to keep firing.
  • Do you work in Git with reviewable changes and a preview deploy before production?
  • Will you fix the cause, or just hide it from Lighthouse?
  • How will you stop it coming back when new pages and tags get added?

Once your vitals pass, go through my technical SEO checklist for Next.js so the rest of the site holds up too.

What's the fastest next step?

Run your slowest page through PageSpeed Insights and paste the report into the Page Speed Fix Planner. If the plan points to hydration, rendering or a tangle of scripts, that's the work I do in technical SEO and Core Web Vitals, and in full Next.js and React builds when a rebuild really is the right call. Send me the report and I'll tell you which fix to do first.

Frequently asked

Why does my Next.js site fail Core Web Vitals when the Lighthouse score is high?+

The Lighthouse score is a lab test on one simulated device, while Core Web Vitals are judged on real Chrome user data. A standard Lighthouse page load can't measure INP, so a Next.js site can score 95 in Lighthouse and still fail INP for real mobile visitors.

What is a good INP score for a website?+

Google treats an INP of 200 milliseconds or less as good and anything over 500 milliseconds as poor, measured at the 75th percentile of real visits, separately for mobile and desktop.

Does Google Tag Manager slow down a Next.js site?+

Often, yes. Tag Manager and other third-party scripts run on the same main thread as your code, so they hurt INP in particular. Remove unused tags first, then load the rest later with the Next.js Script component.

How long do Core Web Vitals fixes take to show up in Search Console?+

Lab tests like Lighthouse change as soon as the fix is deployed. Field data in PageSpeed Insights and Google Search Console is a 28-day rolling window of real visits, so expect a few weeks before the Core Web Vitals report turns green.

Do I need to rebuild my Next.js site to pass Core Web Vitals?+

Usually not. Most Next.js Core Web Vitals failures come from images, fonts, third-party scripts or too many client components, and those can be fixed one template at a time.

How much does it cost to fix Core Web Vitals on a Next.js site?+

Market ranges run from about $200 to $500 for speed optimisation on a simple site (Web Aloha) to $800 to $2,000 for small Next.js fix projects (Upwork). The price depends on which metric fails and how many templates are affected.

Mohit Goyal

Written by Mohit Goyal

Senior Web Developer in Gurugram, India. 100+ fast, SEO-friendly sites shipped in 4+ years with Next.js, React and WordPress, including the procol.ai rebuild. Send me your next project.

Keep reading

Let's build

Have a site that needs to be fast, rank and convert?

Open to Work. Usually replies within a day.