Next.js 15: Turbopack Stable, React 19, and Partial Pre-Rendering
Next.js 15 ships Turbopack as stable, full React 19 support, and Partial Pre-Rendering — here is what changed and how to migrate from v14.
Mahmudul Haque Qudrati
CEO & ML Engineer
One AI engineering post, weekly
LLM benchmarks, prompt techniques, and token-cost breakdowns — not another AI news roundup.
Next.js 15 is a significant release that stabilizes features that have been experimental for over a year. The three headline changes are Turbopack going stable, React 19 becoming the default, and Partial Pre-Rendering landing as an opt-in production feature.
Turbopack Is Now Stable
After months in beta, Turbopack is the default bundler for next dev. The numbers are real: up to 76.7% faster local server startup compared to webpack, and up to 96.3% faster Fast Refresh on large applications.
You do not need to change anything. Run next dev and Turbopack is already active. If you hit an incompatible webpack plugin (rare but possible), opt back out with next dev --turbopack=false.
# Already works — no flags needed
pnpm dev
# Check your build output for Turbopack confirmation
# ✓ Starting...
# ✓ Ready in 432ms ← Turbopack
Team workspace
Ship faster with chat, meetings, and projects in one place — Zlyqor.
React 19 Integration
Next.js 15 requires React 19. The two biggest APIs you will use immediately are:
Server Actions are now stable. You can define async functions in Server Components and pass them as props:
// app/actions.ts
"use server";
export async function createTask(formData: FormData) {
const title = formData.get("title") as string;
await db.tasks.insert({ title });
}
// app/page.tsx
import { createTask } from "./actions";
export default function Page() {
return (
<form action={createTask}>
<input name="title" />
<button type="submit">Add Task</button>
</form>
);
}
The use() hook lets you read promises and context inside render, replacing many useEffect patterns:
import { use } from "react";
function UserName({ userPromise }: { userPromise: Promise<User> }) {
const user = use(userPromise); // suspends until resolved
return <span>{user.name}</span>;
}
Partial Pre-Rendering (PPR)
PPR lets a single route be partly static and partly dynamic — without client-side JavaScript for the static shell. Enable it per-layout or globally:
// next.config.ts
export default {
experimental: {
ppr: true,
},
};
The static shell is served from the CDN immediately. Dynamic holes (wrapped in <Suspense>) stream in after. This gives you the performance of a static site with the flexibility of a dynamic app.
The after() API
Run work after a response has already been sent to the user — perfect for logging, analytics, and non-critical side effects:
import { after } from "next/server";
export async function GET() {
after(() => {
// runs after response is flushed
analytics.track("api_called");
});
return Response.json({ ok: true });
}
Caching Changes
This is the breaking change most teams hit during migration: fetch requests are no longer cached by default. In Next.js 14, every fetch was cached unless you opted out. In v15, you must opt in:
// v14 default (cached)
fetch("/api/data");
// v15 — must be explicit
fetch("/api/data", { cache: "force-cache" }); // cached
fetch("/api/data", { cache: "no-store" }); // no cache (now default)
Run the automated codemod to catch most of these:
npx @next/codemod@canary upgrade latest
instrumentation.ts for Observability
A new top-level file for hooking into the Next.js lifecycle — register OpenTelemetry, Sentry, or custom tracing:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
const { init } = await import("./lib/tracing");
init();
}
}
Migration Notes From v14
- Run
pnpm add next@latest react@latest react-dom@latest - Run the codemod:
npx @next/codemod@canary upgrade latest - Audit all bare
fetch()calls — add{ cache: "force-cache" }where you relied on automatic caching - Update
useFormState→useActionState(React 19 rename) - Remove
forwardRefwrappers — refs now work as regular props
References: Next.js 15 blog · upgrade guide · Turbopack

Mahmudul Haque Qudrati
CEO & ML Engineer
Visionary technologist, software engineer, and machine learning specialist. Founder and CEO of Pristren, directing engineering teams that ship production-grade AI/ML pipelines, mission-critical full-stack applications, and developer tooling. Creator of Zlyqor, the unified team workspace platform. Author of 540+ technical guides and benchmark research reports on large language models, agentic workflows, Model Context Protocol (MCP), and modern web stacks.
More from Mahmudul
Related Articles
How to Build an MCP Server in TypeScript (Step-by-Step)
Build your first MCP server in TypeScript with the official SDK — tools, stdio transport, and a Claude Code test loop in under an hour.
Next.js App Router Patterns in 2026: What to Use and What to Avoid
App Router is the default in Next.js. Here are the patterns that work well in production and the ones that create more problems than they solve.
React Server Components: What They Are and When to Use Them
React Server Components run only on the server and never ship to the browser. Here is what that means in practice and when it actually helps.
// discussion
Comments