Next.js App Router Production Readiness Checklist
A 25-point checklist to make your Next.js App Router application production-ready — covering performance, security, caching, error handling, and observability.
Shipping a Next.js application is easy. Shipping one that stays healthy under real traffic, handles failures gracefully, and gives your team visibility into what is happening — that takes deliberate setup. Most teams discover the gaps only after something breaks in production.
This checklist covers the decisions and configurations that separate a prototype from a production-grade Next.js App Router application. Work through it before your first public launch, and revisit it before each major release.
Architecture and Component Model
- Server components are the default. Every component that does not need browser APIs or local state should be a server component.
use clientshould appear only at leaf nodes. use clientboundaries are as narrow as possible. If only a button is interactive, the button file getsuse client— not the page or section wrapping it.- Server-only code is enforced. Import
server-onlyin any module that accesses secrets, the database, or the filesystem to prevent accidental client-side exposure. - No secrets are passed as props to client components. Only sanitized, presentation-safe data crosses the server-to-client boundary.
Data Fetching
- Parallel fetches use
Promise.all. Independentawaitcalls in the same component are grouped so their latencies do not stack. - Slow data sources are wrapped in
Suspense. Users see partial content immediately; slower sections stream in without blocking initial HTML. generateStaticParamsis configured for dynamic routes. Known slugs are pre-rendered at build time rather than generated on every request.- Database queries use connection pooling. Serverless environments open many connections. A pooler like PgBouncer or a serverless-optimized client prevents exhausting the connection limit.
Caching
- Each data source has an explicit cache policy. No fetch call relies on the default behavior without the team understanding what that default is.
- Tag-based revalidation is wired to mutations. Server Actions that write to the database call
revalidateTagso stale cached data is invalidated immediately. cache: 'no-store'is used sparingly and intentionally. Disabling caching on a fetch that does not change per-request is waste; confirm the reason before opting out.- Sensitive personalized data is not cached. Cache keys that could collide across users do not cache user-specific responses.
Routing and Navigation
- Route groups organize shared layouts. Folders wrapped in parentheses group related routes under a shared layout without polluting the URL.
not-found.tsxanderror.tsxexist at appropriate levels. Every route segment with data fetching has error and not-found boundaries so failures show a recovery UI rather than a blank or broken page.loading.tsxshows meaningful skeletons. Loading states match the shape of the content that replaces them, reducing layout shift.- Middleware matchers exclude static assets. The middleware matcher pattern does not run auth or analytics logic on
/_next/static/,/favicon.ico, or image files.
Security
- All form mutations go through Server Actions with input validation. No user input is trusted before parsing and validation on the server.
- Rate limiting is applied to sensitive endpoints. Login forms, signup flows, and mutation endpoints have rate limits enforced at the middleware or edge layer.
Content-Security-Policyheaders are configured. Next.js supports setting security headers innext.config.jsunderheaders. CSP,X-Frame-Options, andReferrer-Policyare set.- Environment variables are audited. Variables prefixed with
NEXT_PUBLIC_are visible in the browser. Secrets use unprefixed names and are never exposed to the client.
Performance
- Images use
next/image. Allimgtags are replaced with theImagecomponent to enable lazy loading, responsive sizing, and format optimization. - Fonts use
next/font. Local or Google Fonts are loaded throughnext/fontto eliminate layout shift and external font requests. - Bundle analyzer has been run.
@next/bundle-analyzeris used at least once before launch to identify unexpectedly large client-side dependencies. - Core Web Vitals are measured before launch. LCP, CLS, and INP are checked in a production build using Lighthouse or a real-user monitoring tool. Known regressions are addressed before users see them.
Observability
- Structured logging is in place. Application errors and key events write to a log aggregation service, not just
console.log. - Error tracking captures server-side exceptions. A tool like Sentry is configured to capture both server component errors and client-side exceptions.
- Uptime monitoring alerts before users notice. A synthetic monitor pings key routes and alerts when response times degrade or status codes change.
No checklist covers every application's unique requirements, but these twenty-five items address the most common gaps between a working prototype and a production-grade system.
If your team is preparing a Next.js application for launch and wants experienced engineers to review the architecture before go-live, talk to Clixo. We help product teams ship software that holds up.