Next.js App Router: Advanced Performance Patterns
Performance patterns that matter in Next.js App Router — streaming, parallel fetching, caching strategies, and real-world results.
Next.js App Router: Advanced Performance Patterns
The App Router in Next.js 14+ changed how we think about rendering. After shipping several large-scale applications, here are the performance patterns that make the biggest difference.
Streaming with Suspense Boundaries
The most impactful pattern is strategic Suspense boundary placement. Wrap slow data fetches in Suspense to stream the page shell immediately while expensive queries resolve in parallel.
export default function Dashboard() {
return (
<div>
<Header />
<Suspense fallback={<ChartSkeleton />}>
<AnalyticsCharts />
</Suspense>
<Suspense fallback={<TableSkeleton />}>
<RecentTransactions />
</Suspense>
</div>
);
}
Parallel Data Fetching
Never await sequential data calls. Use Promise.all or parallel Server Component rendering to fetch data concurrently. This alone can cut page load times by 50% or more.
Route Groups for Code Splitting
Use route groups to create separate layouts for different sections. This prevents loading unnecessary JavaScript for routes that share a parent layout but have different UI requirements.
Server Actions for Mutations
Replace API routes with Server Actions for form submissions and mutations. They reduce client-side JavaScript, provide built-in progressive enhancement, and simplify error handling with native form state.
Caching Strategy
Configure caching at the fetch level with revalidation intervals. Use unstable_cache for Prisma queries and set sensible TTLs based on data freshness requirements. Over-caching is better than no caching — you can always reduce TTLs later.
Results
These patterns consistently deliver sub-100ms Time to First Byte and Lighthouse scores above 95. The key is measuring performance continuously and optimizing the critical rendering path.