Next.js 15: The Developer's Guide to App Router, Server Components, and Turbopack

Photo: Meet Patel / Pexels
Next.js 15 shipped in October 2024 and resolved a question the React community had been debating since the App Router preview: which router is actually the one to use? The answer became official — the App Router is the default, the Pages Router is supported but not where new investment goes, and the mental model of React Server Components is now the foundation of how Next.js applications are structured. This guide covers what changed, why the architectural decisions were made the way they were, and what developers evaluating or migrating to the Next.js 15 architecture need to understand. Note that Next.js 16 (October 2025) is now current; where it changes behavior meaningfully, this guide notes the differences.
What Next.js Is and Why It Exists
Next.js — a React-based web framework developed and maintained by Vercel, first released in 2016. It adds server-side rendering, static site generation, routing, image optimization, and deployment infrastructure on top of React, which handles only the component model.
React itself is a JavaScript library for building user interfaces. It defines how components look and behave, but does not specify how to route between pages, how to fetch data, how to render HTML for search engines, or how to deploy the result. Next.js answers all of those questions with opinionated defaults that work well for most applications.
The framework occupies a specific position in the stack: above bare React (which requires you to answer those questions yourself) and below fully managed platforms (which answer them for you but remove control). A developer who understands Next.js can build a marketing site, a SaaS dashboard, an e-commerce store, or an API — on the same codebase, with the same mental model.
Vercel — the company that created and maintains Next.js. It also operates a deployment platform optimized for Next.js. The framework is open-source and deployable anywhere that runs Node.js; Vercel's platform is not required.
Source: Next.js official documentation at nextjs.org — architecture overview and framework philosophy. Vercel company background at vercel.com/about.
The Two Routers: What Changed and Why
Next.js had one routing system from 2016 through 2022: the Pages Router. Files in the /pages directory mapped to URL routes. Data fetching happened in getServerSideProps or getStaticProps functions. It was understandable, well-documented, and worked.
Pages Router — Next.js's original file-based routing system where /pages/about.tsx maps to /about. Data fetching uses special exported functions (getServerSideProps, getStaticProps). Client-side rendering uses useEffect. This router remains supported in Next.js 15 and 16.
The App Router, introduced as stable in Next.js 13 and made the default in Next.js 15, is a different architectural model. Files live in an /app directory. The routing still follows the filesystem, but the data-fetching model changed completely, and the rendering model changed with it.
App Router — Next.js's current default routing system, introduced stable in Next.js 13.4 and made the explicit recommended default in Next.js 15. Uses the /app directory. Components are React Server Components by default, enabling server-side data fetching directly inside components without special exported functions.
The key question developers ask when first encountering the two routers: can I use both? Yes — they coexist in the same project, which allows incremental migration. But they do not share state and cannot share layouts. A route is either in /pages or /app; it cannot be in both.
Source: Next.js blog — "Next.js 15" (October 2024) at nextjs.org/blog/next-15 — official release notes covering the App Router becoming the default-documented system.
Source: Next.js documentation — "App Router vs Pages Router" comparison at nextjs.org/docs.
React Server Components: The Core Architectural Shift
The reason the App Router required a new mental model is React Server Components — a rendering mode where components execute on the server and send HTML (not JavaScript) to the client.
React Server Components (RSC) — a rendering model where React components run on the server, have direct access to server resources (databases, file systems, environment variables), and send pre-rendered HTML to the client. They do not ship JavaScript to the browser and cannot use browser APIs or React hooks.
Think of Server Components like a kitchen that only operates in the restaurant. The meal (HTML) leaves the kitchen and goes to the table (the browser), but the kitchen itself (the server) stays behind. The browser receives the finished output, not the recipe or the ingredients. This is different from traditional React, where the browser receives the recipe (JavaScript) and cooks the meal itself — which is why traditional React apps require a JavaScript download before the page becomes interactive.
The practical implications are significant:
No data-fetching boilerplate. In the Pages Router, fetching data from a database required exporting a getServerSideProps function that ran on the server and passed data as props to the component. In the App Router with Server Components, the component itself can be async and await a database query directly. The component and the data fetching are co-located.
Zero JavaScript bundle cost. A Server Component sends zero JavaScript to the client. This matters for performance: a large data-display component that renders a table from database results needs no client-side JavaScript at all if it is a Server Component.
No access to browser APIs. Server Components cannot use useState, useEffect, onClick, or any browser-specific API. For interactivity, you use Client Components.
Client Component — a React component marked with the "use client" directive that runs in the browser. Has access to browser APIs, React hooks, and event handlers. Sends JavaScript to the browser.
The mental model for deciding which type to use: if a component needs interactivity (button clicks, form input, real-time updates), it is a Client Component. If it only needs to display data, it is a Server Component. Server Components can import Client Components; Client Components cannot import Server Components.
Source: React documentation — "Server Components" at react.dev/reference/rsc/server-components — canonical description of the Server Components model, its constraints, and usage patterns.
Source: Next.js documentation — "Server and Client Components" at nextjs.org/docs/app/building-your-application/rendering/server-components.
Turbopack: Why It Is Faster and What It Changed
Turbopack — a Rust-based JavaScript bundler developed by Vercel as a replacement for Webpack. Turbopack became stable for development builds in Next.js 15. It became stable for production builds in Next.js 16.
Webpack, which powered Next.js development builds until Turbopack, is written in JavaScript. Bundling — the process of taking thousands of source files and combining them into optimized output — is computationally intensive. Writing it in Rust, a compiled systems language, yields substantially better performance because Rust programs execute faster than JavaScript programs for CPU-bound work.
The performance improvement is measurable. Next.js 15's release benchmarks showed Turbopack delivering up to 45.8% faster initial route compilation without caching, and up to 96.3% faster code updates (hot module replacement — the reload that appears when you save a file during development). For large applications with hundreds of routes, this translates to minutes saved in a typical development session.
Hot module replacement (HMR) — a development feature that updates specific modules in the browser without a full page reload when source files change. The developer saves a file and sees the result in under a second without losing application state.
Bundling — the process of combining source code files (JavaScript, TypeScript, CSS) and their dependencies into optimized output files suitable for delivery to a browser. Without bundling, a modern web application might require hundreds of individual network requests for its source files.
Turbopack uses incremental computation: it tracks which parts of the codebase depend on which other parts and only reprocesses what has actually changed. Webpack rebuilds larger portions of the dependency graph on each change. For a developer making small, frequent edits, this difference is pronounced.
The production build improvement in Next.js 16 extended these gains to the final output. Vercel's benchmarks show production builds completing faster compared to Webpack, with equivalent or better output optimization.
Source: Next.js blog — "Next.js 15" at nextjs.org/blog/next-15 — Turbopack development stability announcement, benchmark data (45.8% faster initial compile, 96.3% faster HMR).
Source: Next.js blog — "Next.js 16" at nextjs.org/blog/next-16 — Turbopack production build stability announcement.
Async Request APIs: The Breaking Change to Know
Next.js 15 introduced a change that caught many developers mid-migration: several APIs that were previously synchronous became asynchronous. This is the primary source of migration friction between Next.js 14 and Next.js 15.
The affected APIs include cookies(), headers(), params, and searchParams. In Next.js 14, you could access these synchronously:
// Next.js 14 (Pages Router pattern)
const cookieStore = cookies()
const token = cookieStore.get('token')
In Next.js 15 App Router, these APIs are async:
// Next.js 15 (App Router)
const cookieStore = await cookies()
const token = cookieStore.get('token')
Why the change? Request-specific data (cookies, headers, URL parameters) belongs to a specific incoming HTTP request. Making it async aligns with how server-side rendering actually works — components that need this data are inherently request-specific and cannot be statically generated. The async signature makes this dependency explicit, enabling better optimization of components that do not depend on request data.
The migration path: Next.js 15 ships a codemod — an automated code transformation tool — that handles the most common cases. Running npx @next/codemod@canary upgrade latest in the project root handles many of the changes automatically. The remaining cases require manual review.
Codemod — an automated code transformation script that modifies source code according to a set of rules, used when a framework or language version change requires widespread but mechanical code updates.
Source: Next.js documentation — "Upgrading from Next.js 14 to 15" at nextjs.org/docs/app/guides/upgrading/version-15 — official migration guide with codemod instructions and manual change documentation.
The Rendering Models: Static, Dynamic, and Partial Pre-Rendering
One source of confusion in the App Router is the number of rendering modes available and how Next.js decides which one applies. Understanding the decision tree clarifies both behavior and performance.
Static rendering — the page is rendered at build time and the result is cached. Identical for every visitor. Best for pages whose content does not change frequently (blog posts, marketing pages, documentation). The default for routes that do not use dynamic data.
Dynamic rendering — the page is rendered at request time on the server. Appropriate for pages that depend on data unique to the request (user-specific dashboards, pages with cookies or headers, real-time data). Triggered automatically when a component uses cookies(), headers(), or searchParams.
Incremental Static Regeneration (ISR) — a mode where a statically generated page is regenerated in the background after a specified time interval, serving the cached version until regeneration completes. Configured via export const revalidate = <seconds> in a route segment.
Partial Pre-Rendering (PPR) — introduced as experimental in Next.js 14, stabilized in Next.js 16. Allows a single route to serve a static shell immediately (from cache) while streaming dynamic content into it as it becomes available. Like a restaurant that puts pre-set cutlery and breadbasket on the table immediately while your actual order is being prepared.
PPR is the most important architectural addition in the Next.js 16 era for performance-conscious applications. The static shell — navigation, layout, above-the-fold content — appears instantly from cache. The dynamic personalized content streams in as the server resolves it. This eliminates the traditional choice between "fast but stale" (full static) and "fresh but slow" (full server rendering).
| Rendering Mode | When It Renders | Cache Behavior | Best For |
|---|---|---|---|
| Static | Build time | Indefinitely cached | Blog posts, docs, marketing |
| ISR | Build time + revalidation interval | Refreshed on schedule | Product listings, news |
| Dynamic | Every request | Not cached | User dashboards, personalized content |
| PPR (Next.js 16) | Static shell at build; dynamic parts at request | Shell cached, dynamic streamed | Most production applications |
Source: Next.js documentation — "Rendering" section at nextjs.org/docs/app/building-your-application/rendering — covers all rendering modes with code examples.
Source: Next.js blog — "Next.js 16" at nextjs.org/blog/next-16 — PPR stable announcement and Cache Components introduction.
When to Use Next.js (And When Not To)
Next.js is the right choice for a specific set of applications. It is not always the right choice, and recognizing the mismatches saves significant time.
Use Next.js when: you are building a React application that needs server-side rendering or static generation for SEO or performance; you want a unified codebase for both the frontend and a Node.js API backend; you are deploying to Vercel or a Node.js-capable host; or your team is already comfortable with React and wants opinionated structure.
Consider alternatives when: your application is primarily a client-side single-page app with no SEO requirements (Vite + React is simpler and faster to start); you need a different backend language (Next.js is Node.js only; a separate backend API may be more appropriate); or you are building a simple static site with no dynamic features (Astro or Hugo are lighter).
The learning curve is real. The App Router with Server Components, Turbopack, async request APIs, and PPR represents a genuinely new mental model compared to both the Pages Router and to standard React development. Developers coming from the Pages Router face meaningful refactoring. Developers new to React face learning both React and Next.js's architectural patterns simultaneously. Both are manageable, but timelines should account for the learning investment.
Team readiness matters more than feature lists. An experienced Pages Router team can build excellent applications in the Pages Router, which remains fully supported. Migrating to the App Router for its own sake — without specific needs it addresses — adds churn without benefit. Migrate when you are building something new, when PPR would solve a real performance problem, or when you are onboarding developers who will learn the App Router first.
Source: Next.js documentation — "Migrating from Pages Router to App Router" at nextjs.org/docs/app/guides/migrating/app-router-migration.
Deployment: Beyond Vercel
Next.js runs on any platform that supports Node.js. Vercel is the path of least resistance — zero-configuration deployment, automatic edge caching, built-in analytics, and first-party support for all Next.js features including PPR. But the lock-in question is legitimate.
Self-hosting options that support the full Next.js feature set include: a Node.js server running next start, Docker containers (Next.js ships a Dockerfile example in its documentation), and platform-as-a-service providers including Netlify, AWS Amplify, Railway, and Fly.io. Static exports (output: 'export' in next.config.ts) allow deployment to any CDN, but disable all server-side features.
The trade-off with Vercel: features like PPR and Edge Middleware perform best on Vercel's infrastructure because they are co-designed. Running the same features on a single-origin Node.js server works but may not achieve the same global latency profile. For applications serving a geographically concentrated user base, this difference is often not material.
Docker deployment pattern: the multi-stage Dockerfile in Next.js's official documentation produces a minimal production image. Build the application in a Node.js build stage, copy the production output to a clean Node.js runtime image, run next start. This is the recommended path for container-based deployments on Kubernetes, ECS, or similar platforms.
Source: Next.js documentation — "Self-Hosting" at nextjs.org/docs/app/deploying — covers Node.js server, Docker, and static export deployment options.
What Next.js 16 Changed (And Why the Slug Stays "15")
This article's slug reflects the URL that was indexed when Next.js 15 was current. Next.js 16 shipped in October 2025 with two headline changes worth noting for developers on either version.
Turbopack production stability. In Next.js 15, Turbopack was stable for development but still experimental for production builds. Next.js 16 made it the default bundler for both. The practical effect: next build now uses Turbopack by default, with Webpack available as an escape hatch for projects with Webpack-specific plugins.
Cache Components. Next.js 16 introduced a use cache directive and a <Cache> component that makes PPR's caching behavior more explicit and composable. Rather than routing-level static/dynamic decisions, individual component trees can be cached with specific revalidation strategies. This is a more granular model that enables fine-tuned performance optimization at the component level.
Migration from Next.js 15 to 16 is less disruptive than the 14-to-15 migration. The async request API changes were the major breaking point; Next.js 16 builds on the same model. The codemod (npx @next/codemod@canary upgrade latest) handles the most common changes.
Source: Next.js blog — "Next.js 16" at nextjs.org/blog/next-16 — official release notes covering Turbopack production builds, Cache Components, and Node.js middleware stability.
Source: Next.js blog — "Next.js 15.4" at nextjs.org/blog/next-15-4 — intermediate release covering Turbopack build improvements in beta during the 15.x series.
Frequently Asked Questions
Q: What is the difference between the App Router and the Pages Router in Next.js?
A: The Pages Router (the original system) lives in the /pages directory, uses exported functions (getServerSideProps, getStaticProps) for server-side data fetching, and treats all components as client-rendered React by default. The App Router (default since Next.js 15) lives in the /app directory, makes components server-rendered by default via React Server Components, allows async data fetching directly inside components, and enables Partial Pre-Rendering. Both routers work in the same project and the Pages Router remains fully supported.
Q: What are React Server Components and why do they matter?
A: React Server Components are components that run on the server and send pre-rendered HTML to the browser, with zero JavaScript shipped to the client. They can directly access databases, file systems, and environment variables without an intermediate API layer. They cannot use browser APIs or React hooks. The benefit: faster page loads (no JavaScript to parse for server-rendered content), simpler data fetching (no useEffect + API call pattern for data that originates on the server), and reduced bundle size.
Q: What is Turbopack and how fast is it compared to Webpack?
A: Turbopack is a Rust-based bundler developed by Vercel to replace Webpack. In Next.js 15, it is stable for development builds. Next.js 15 benchmarks show up to 45.8% faster initial route compilation and up to 96.3% faster hot module replacement compared to Webpack. In Next.js 16, Turbopack became the default production bundler as well. The speed improvement comes from Rust's performance characteristics for CPU-bound work and Turbopack's incremental computation model that only reprocesses changed code.
Q: Should I migrate from the Pages Router to the App Router?
A: Not necessarily for existing projects. The Pages Router is fully supported with no announced end-of-life. Migrate if: you are starting a new project (always use App Router), you need PPR for performance, or you are hiring developers who will learn the App Router first. Migrating an existing Pages Router application adds risk and refactoring cost without guaranteed benefit unless you have a specific need the App Router addresses. Coexistence (partial migration) is supported.
Q: Does Next.js require deployment on Vercel?
A: No. Next.js is open-source and deployable anywhere that runs Node.js — Docker containers, AWS, Google Cloud, Railway, Fly.io, Netlify, and self-managed servers. Some features (PPR, Edge Middleware) work most efficiently on Vercel's globally distributed infrastructure. For applications with geographically concentrated users or single-region requirements, self-hosted deployment is fully viable. A next start command on a Node.js server or a Docker container is the standard self-hosted deployment pattern.
Q: What changed between Next.js 14 and Next.js 15 that might break my code?
A: The primary breaking changes in Next.js 15 were the async request APIs. Functions like cookies(), headers(), params, and searchParams changed from synchronous to asynchronous — meaning code that accessed them without await stopped working. Next.js provides a codemod (npx @next/codemod@canary upgrade latest) that handles most of these changes automatically. Other changes include: Turbopack became the default dev server, caching behavior became opt-in rather than opt-out by default for fetch calls, and Server Actions security was improved with unguessable endpoints.
Related reading:
Follow new articles
Add SciHub101 to your feed reader to see new science and technology stories.
About the Author
SciHub101 is an independent science and technology publication founded and edited by Buğra Sözeri, a software engineer and app developer based in Türkiye. AI tools assist with drafting and research. Source documentation in the existing archive is uneven, and articles are being reviewed and corrected. The Editorial Team byline identifies editorial responsibility; it does not certify specialist or independent human review. Where we compare products, anything built by our own team is labelled as such — see the editorial guidelines and About page for how corrections and disclosures work.
Related Articles

Open Source Software: Licenses, Economics, and Why It Powers the Internet
Open source software underpins the global internet, powering 96% of Fortune 500 companies' web servers, the entire Linux ecosystem, and billions of devices from Android phones to cloud infrastructure. Yet 'open source' means something precise: source code publicly available under a legal license that permits modification, redistribution, and private use, with no single vendor lock-in. This article examines the three dominant license models (GPL, MIT, Apache), how projects sustain themselves through sponsorship and foundations, the economics that make open source viable, and why enterprises depend on it despite the paradox of free software powering trillion-dollar industries.

How Websites Detect You Are Using an Ad Blocker
Ad blocker detection is an arms race measured in weeks. Publishers have developed at least six distinct techniques to identify blocked ads — some require no JavaScript at all. The methods exploit how browsers handle missing resources, render CSS, process HTTP responses, and load network requests. Each technique reveals a different assumption about what ad blockers must do to function.

React vs Vue vs Svelte 2026 — Which Framework to Learn?
Compare React, Vue, Svelte side-by-side. Job market demand, learning curve, salary, real-world usage. Which one to choose.

Zustand vs Redux — React State Management
Zustand vs Redux compared: bundle size, boilerplate, API, when to use each, plus how Jotai, Valtio, MobX, and TanStack Query fit in 2026.

What Is the Vercel AI SDK? LLM Toolkit
The Vercel AI SDK is a TypeScript toolkit for building LLM apps with React, Next.js, Svelte, and Vue. Unified API, streaming, tools, structured outputs.

What Is HTMX? Hypermedia for Modern Web
HTMX explained: how this 14KB library lets you build dynamic web apps with HTML attributes instead of a JavaScript framework, plus how it actually works.