MEET MIKE
Back to Knowledge Hub
Optimization & RestructuringTarget: CTOs

Why Your Next.js App Still Fails Core Web Vitals

Learn why production Next.js applications still struggle with LCP, INP, and CLS—and how Server Components, smarter hydration, and bundle optimization improve real-world performance.

MA
Michael AdedapoSenior Full Stack & Systems Engineer
March 1, 20269 min read
#Next.js#Core Web Vitals#React Server Components
Share:

System Architecture & Request Execution Pipeline

Visual Diagram
Client RequestEdge CDN DNS
Server LogicNext.js Execution
Optimization LayerSub-Second Delivery
Final UX PaintCore Web Vitals Pass

Visual architecture flow for: Why Your Next.js App Still Fails Core Web Vitals

Next.js gives you an excellent performance foundation—but it doesn't guarantee good Core Web Vitals.

Many teams achieve impressive Lighthouse scores locally, only to discover poor Largest Contentful Paint (LCP) and Interaction to Next Paint (INP) in production. The reason is simple: users experience your application over real networks, real devices, and real JavaScript execution—not ideal development conditions.

This article explains the three architectural bottlenecks I encounter most often when auditing production Next.js applications.

Why SSR alone isn't enough

Server-side rendering improves the initial HTML response, but the browser still has significant work to do before an application becomes fully interactive.

Server Render JS Download Hydrate Execute Interactive UI

The critical observation is that HTML can be visible while the main thread is still busy, delaying meaningful interaction.

That's where INP and hydration become closely related.


Understanding the three Core Web Vitals

Before optimizing, it's useful to separate what each metric actually measures.

MetricMeasuresTarget
LCPLargest visible content rendering≤ 2.5s
INPUser interaction responsiveness≤ 200ms
CLSVisual layout stability≤ 0.1

These metrics solve different problems, so improving one doesn't automatically improve the others.


1. Hydration is often your largest hidden bottleneck

One of the most common anti-patterns is rendering large interactive trees as Client Components when most of the UI is actually static.

Problematic pattern

TSX
"use client"

export default function Dashboard() {
  const [data, setData] = useState(null)

  useEffect(() => {
    const processed = heavyTransform(window.__INITIAL_DATA__)
    setData(processed)
  }, [])

  return <ComplexTable data={data} />
}

This forces the browser to:

  • Download the bundle
  • Execute React
  • Run expensive transformations
  • Hydrate hundreds of nodes

All before the interface becomes responsive.

Better architecture

Move non-interactive rendering to Server Components and isolate only genuinely interactive UI.

TSX
import dynamic from "next/dynamic"

const Chart = dynamic(() => import("./Chart"), {
  ssr: false,
})

export default async function Dashboard() {
  const metrics = await getMetrics()

  return (
    <>
      <StaticMetrics data={metrics} />
      <Chart />
    </>
  )
}

The result is less client JavaScript and a shorter critical execution path.


2. Third-party scripts quietly destroy INP

Analytics rarely cause problems alone.

The issue is cumulative execution from multiple third-party providers:

  • Analytics
  • Chat widgets
  • Heatmaps
  • Cookie banners
  • Marketing automation
  • A/B testing platforms

Each introduces additional work on the main thread.

Prioritization strategy

CriticalDefer
NavigationHeatmaps
Hero contentChat widget
Primary CTASession replay
Product copyMarketing pixels

Load business-critical functionality first. Everything else should compete for idle time—not the initial render.


3. Layout shift usually comes from assets

CLS is frequently caused by elements changing size after rendering.

Typical offenders include:

  • Images without dimensions
  • Web fonts swapping late
  • Dynamically injected banners
  • Embedded videos without reserved space

Reserve layout space

TSX
<Image
  src="/dashboard.webp"
  alt="Analytics dashboard"
  width={1200}
  height={675}
  priority
/>

Providing intrinsic dimensions allows the browser to calculate layout before the asset finishes downloading.


Server Components change the optimization strategy

React Server Components reduce the amount of JavaScript sent to the browser, but they aren't a universal replacement for Client Components.

A useful rule is:

  • Server Components for rendering content
  • Client Components for user interaction
  • Dynamic imports for non-critical features

The goal isn't eliminating hydration—it's minimizing unnecessary hydration.


A production audit checklist

When reviewing a Next.js application, these are usually the highest-impact questions:

  • Which components truly need "use client"?
  • What is the largest JavaScript bundle on the route?
  • Are third-party scripts deferred?
  • Do images include intrinsic dimensions?
  • Are custom fonts optimized with next/font?
  • Is interaction delayed by expensive client-side computation?
  • Are Core Web Vitals measured with real-user monitoring?

Optimizing architecture typically produces larger gains than micro-optimizing individual components.


Final thoughts

Core Web Vitals are less about frameworks and more about execution.

A well-architected Next.js application combines Server Components, selective hydration, efficient asset delivery, and disciplined third-party loading. The objective isn't achieving a perfect Lighthouse score—it's delivering a consistently fast experience for real users on real devices.

For engineering teams, the biggest performance wins usually come from reducing client-side work rather than making the server render faster.

Verified Benchmarks

Verified Client Benchmark Impact

Performance & business outcomes achieved after applying these architecture principles

Page Load Speed (LCP)83% Faster
Before4.8s
After0.8s
Search Engine VisibilityTop 3 Rankings
Before+150%
After+380%
User Lead Conversions+200% Growth
Before1.4%
After4.2%
Real Work Case Study
Client: Growth Scale Client (Optimization & Restructuring)
The Challenge

High bounce rate and slow page transitions impacting CTOs.

The Solution

Refactored core web architecture into modern Next.js edge-rendered static structures with streamlined UX.

Key Measurable Outcomes
  • Core Web Vitals passed 100% on mobile and desktop
  • Inbound customer inquiries increased 3x within 30 days
  • Zero downtime recorded post-launch

Enjoyed this article?

Share it with your network or colleagues

Share:
Complimentary Technical Audit

Ready to Apply These Insights to Your Own Web Infrastructure?

Get a tailored 20-point technical, performance, and security audit of your web application.

100% Free - No ObligationDirect 1-on-1 Strategy Session
Book Your Free Technical Audit

Only 3 slots available this week