Back to Blog
DevelopmentApr 15, 2026·9 min read·Ribbsaeter Systems Engineering

The Next.js Performance Audit We Run on Every Client Project

Our 30-point performance checklist for Next.js applications — covering Core Web Vitals, bundle size, server components, image optimization and the database queries nobody thinks to profile.

Key takeaways

  • 01Server Components eliminate client-side data-fetching waterfalls — the single biggest performance lever in Next.js 14+.
  • 02Bundle analysis should happen in CI, not as an afterthought. We flag any page bundle over 150KB compressed.
  • 03next/image with a CDN and correct priority flags typically cuts LCP by 200-500ms on image-heavy pages.
  • 04Database queries are the invisible bottleneck: add connection pooling (PgBouncer or Supabase pooler) and profile every query that runs on critical paths.
  • 05Cache-control headers on static assets and ISR for semi-dynamic pages eliminate unnecessary server round-trips.

Every quarter we audit the Next.js applications we maintain — and every quarter we find performance wins that are hiding in plain sight. Not because the framework is slow, but because it is easy to use the framework in ways that are slow. After running this process across fintech dashboards, e-commerce storefronts, marketplace platforms and SaaS tools, the patterns are remarkably consistent.

1. Server Components: eliminate client waterfalls

The single biggest performance lever in Next.js 14+ is moving data fetching from client components (useEffect, SWR, React Query) to Server Components. A server component fetches data at the edge or origin, renders HTML, and streams it to the client — the browser never sees a loading spinner. This eliminates the client-side waterfall where the browser downloads JS, parses it, executes it, fetches data, then finally renders content. On data-heavy pages we routinely see Time to First Byte improve by 40-70% after this migration.

2. Bundle analysis in CI

We add @next/bundle-analyzer to every project and run it in CI on every PR that changes dependencies. Our threshold: no page bundle should exceed 150KB compressed. When it does, we audit the imports. Common offenders: importing an entire icon library instead of individual icons, pulling in moment.js when Intl.DateTimeFormat exists, and barrel files that re-export hundreds of modules.

# Add to CI pipeline
ANALYZE=true next build
# Then check .next/analyze/client.html for oversized chunks

3. Image optimization

next/image handles format conversion (WebP/AVIF), resizing and lazy loading — but only if you use it correctly. The priority prop must be set on above-the-fold images (hero, logo) to preload them. The sizes prop must match your responsive layout to avoid downloading oversized images. And the images should be served from a CDN, not directly from the Next.js server. Getting this right typically improves LCP by 200-500ms on image-heavy pages.

4. Database and API profiling

The slowest part of most Next.js applications is not React rendering — it is the database query that runs during server-side rendering. We profile every query that runs on critical render paths using PostgreSQL's EXPLAIN ANALYZE, add connection pooling (PgBouncer for self-hosted, Supabase's built-in pooler for managed), and ensure indexes exist for every query pattern. N+1 queries in Server Components are particularly insidious because they do not show up as client-side loading spinners — they just make TTFB slow.

5. Caching strategy

Next.js provides four caching layers: the fetch cache (per-request), the Data Cache (cross-request), the Full Route Cache (pre-rendered pages), and the Router Cache (client-side). We configure all four explicitly rather than relying on defaults. Static pages use ISR with appropriate revalidation periods. Dynamic pages set cache-control: private, no-store. Static assets (JS, CSS, images) get immutable, max-age=31536000. Misconfigured caching is the most common reason for both stale content and unnecessarily slow pages.

6. Third-party scripts

Analytics, chat widgets, A/B testing tools, cookie consent banners. Each adds 20-100KB of JavaScript and often blocks the main thread during load. We audit every third-party script, load them with next/script strategy='lazyOnload' or afterInteractive, and remove any that are not actively providing business value. A client's marketing team once added six analytics tools. After audit, two were active and four were loading 400KB of dead JavaScript on every page.

The full checklist

AreaCheckTarget
Core Web VitalsLCP< 2.5s on 75th percentile
Core Web VitalsCLS< 0.1
Core Web VitalsINP< 200ms
BundlePer-page JS (compressed)< 150KB
BundleTotal shared JS< 120KB
ServerTTFB (p95)< 400ms
ServerServer Component render time< 100ms
DatabaseCritical-path query time< 50ms each
ImagesAbove-fold imagespriority prop set, CDN-served
CachingStatic assetsimmutable, max-age=31536000
Third-partyTotal third-party JS< 100KB

How we deliver this

Performance auditing is built into our development and maintenance services. For new builds, the checklist is enforced from sprint one. For existing applications, we run a standalone audit that produces a prioritised list of improvements with estimated impact. The goal is never perfection on paper — it is measurable improvement on the metrics that affect real users and conversion rates.

Frequently asked questions

Direct answers to questions readers and AI assistants commonly ask about this topic.

How often should you audit Next.js performance?+

At minimum, quarterly. Performance degrades gradually as features are added, dependencies are updated and third-party scripts accumulate. We build performance checks into CI so regressions are caught on every PR, with a deeper manual audit each quarter.

What is a good LCP score for a Next.js site?+

Google considers LCP under 2.5 seconds 'good'. For competitive markets (e-commerce, SaaS, fintech) we target under 1.5 seconds. With Server Components, CDN-served images and proper caching, sub-1-second LCP is achievable for most pages.

Do Server Components automatically make a site faster?+

Not automatically. Server Components eliminate client-side data waterfalls, which is a major win. But they can introduce server-side waterfalls if queries are not parallelized, and they increase server load if not cached properly. The framework gives you the tools — the architecture determines the outcome.

Last updated: April 27, 2026 · Written by Ribbsaeter Systems Engineering · Performance & Full-Stack Engineering