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 chunks3. 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
| Area | Check | Target |
|---|---|---|
| Core Web Vitals | LCP | < 2.5s on 75th percentile |
| Core Web Vitals | CLS | < 0.1 |
| Core Web Vitals | INP | < 200ms |
| Bundle | Per-page JS (compressed) | < 150KB |
| Bundle | Total shared JS | < 120KB |
| Server | TTFB (p95) | < 400ms |
| Server | Server Component render time | < 100ms |
| Database | Critical-path query time | < 50ms each |
| Images | Above-fold images | priority prop set, CDN-served |
| Caching | Static assets | immutable, max-age=31536000 |
| Third-party | Total 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