SpeedPriority
Toggle menu
Next.js

How Fast Is Your Next.js Site?

Next.js gives you every tool needed to build a fast site — and plenty of ways to accidentally build a slow one. Field data shows Next.js sites struggle on mobile more than you'd expect. Test yours below.

Next.js Core Web Vitals: What the Field Data Shows

Real-user performance of every measured Next.js origin, from the Chrome UX Report (May 2026).

32.9%of Next.js sites pass all three Core Web Vitals on mobile

LCP
52%
INP
58.7%
CLS
69.1%
TTFB
47.9%
FCP
50.1%

Share of origins with a good score per metric (mobile, 311,587 Next.js origins measured). Data: May 2026, HTTP Archive Core Web Vitals Technology Report / Chrome UX Report.

The surprise in this data: Next.js sites pass Core Web Vitals less often than WordPress sites on mobile. The gap is interactivity — INP. Shipping large client bundles that hydrate on mid-range phones keeps the main thread busy long after the page looks ready. Teams that move logic into Server Components and cache rendered output usually recover both INP and TTFB quickly.

The 3 Most Common Next.js Performance Bottlenecks

1.Heavy hydration hurting responsiveness (INP)

INP is Next.js's weakest mobile metric by far. Marking whole page trees "use client" ships and hydrates far more JavaScript than needed, so early taps and inputs wait on a busy main thread — especially on mid-range Android devices.

How to fix it: Keep components server-first: push "use client" to the smallest leaf components possible, and load heavy, below-the-fold widgets dynamically so they stay out of the initial bundle. Note that ssr: false only works inside a Client Component — put the dynamic import in the leaf that owns the widget.

// Inside a Client Component: keep heavy widgets out of the initial bundle
import dynamic from "next/dynamic";

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

2.LCP image missing priority

next/image lazy-loads by default. When the hero image is the LCP element and nobody set priority, the browser discovers it late and LCP slips past 2.5 s even though everything else is fast.

How to fix it: Add the priority prop to the above-the-fold image (and only that one) so Next.js preloads it with high fetch priority.

import Image from "next/image";

<Image src="/hero.jpg" width={1200} height={600}
       priority alt="..." />

3.Uncached server rendering (TTFB)

Rendering every request dynamically — often triggered accidentally by reading cookies/headers or by fetch with no caching — means each visitor waits for your server (and its data sources) before anything paints. Fewer than half of Next.js sites hit the good-TTFB bar on mobile.

How to fix it: Render static wherever possible and revalidate in the background (ISR). Check your build output: routes marked ƒ (Dynamic) that don't need per-request data are TTFB paid for nothing.

// app/page.tsx — serve cached HTML, refresh it hourly
export const revalidate = 3600;

Frequently Asked Questions

Why is my Next.js site fast on desktop but slow on mobile?

Usually hydration cost. Desktop CPUs absorb large client bundles; mid-range phones don't, so INP suffers. Field data shows the desktop-to-mobile gap for Next.js INP is dramatic — about 94% pass on desktop versus under 60% on mobile. Reducing client-side JavaScript is the highest-leverage fix.

Does the App Router improve Core Web Vitals?

It can. Server Components let you ship significantly less JavaScript, which directly helps INP, and streaming improves perceived loading. But the defaults don't guarantee it — a fully client-rendered App Router page performs no better than the old Pages Router. Measure first, then move heavy logic to the server.