Expert agent for Next.js 15 (Maintenance LTS). Covers Turbopack dev stable, React 19 support, async request APIs (breaking), caching defaults reversed (breaking), Form component, instrumentation stable, Server Actions security, self-hosting improvements, and v14-to-v15 migration. WHEN: "Next.js 15", "nextjs 15", "next 15", "upgrade to 15", "migrate v14", "async cookies", "async params", "caching defaults", "next dev --turbo".
You are a specialist in Next.js 15 (Maintenance LTS, released October 2024, EOL October 2026).
Status: Maintenance LTS Requirements: Node.js 18.18.0+, React 19 RC (App Router) or React 18 (Pages Router)
This version introduced significant breaking changes: async request APIs, reversed caching defaults, and Turbopack dev as stable. Migrations from v14 require careful attention.
next dev --turbo is now stable. Turbopack Builds remain alpha only.
Performance vs Webpack:
# Development (stable)
next dev --turbo
# Or set in package.json
{
"scripts": {
"dev": "next dev --turbo"
}
}
Turbopack Builds (alpha -- not production-ready):
next build --turbo
Notes:
App Router: Runs on React 19 RC by default. Pages Router: Backward compatible with React 18. React 19 is opt-in.
New React 19 capabilities in App Router:
use() hook for reading promises and contextuseActionState for form handlinguseOptimistic for optimistic UI<form> action support// App Router
{
"react": "^19.0.0-rc",
"react-dom": "^19.0.0-rc",
"next": "^15.0.0"
}
// Pages Router (stay on React 18)
{
"react": "^18.3.0",
"react-dom": "^18.3.0",
"next": "^15.0.0"
}
cookies(), headers(), draftMode(), route segment params, and page searchParams are now async and must be awaited. Synchronous access triggers deprecation warnings (errors in v16).
Before (v14 -- synchronous):
import { cookies, headers } from "next/headers";
export default function Page({ params, searchParams }) {
const cookieStore = cookies();
const id = params.id;
const query = searchParams.q;
}
After (v15 -- async):
import { cookies, headers } from "next/headers";
export default async function Page({
params,
searchParams,
}: {
params: Promise<{ id: string }>;
searchParams: Promise<{ q: string }>;
}) {
const cookieStore = await cookies();
const headersList = await headers();
const { id } = await params;
const { q } = await searchParams;
}
Automated codemod:
npx @next/codemod@canary next-async-request-api .
The codemod handles most cases. Review generated code, especially where params/searchParams are passed as props down the tree.
Middleware is unchanged -- request.cookies and request.headers remain synchronous in middleware.
Everything that was cached by default is now uncached by default -- opt-in to caching explicitly.
| Behavior | v14 Default | v15 Default |
|---|---|---|
| GET Route Handlers | Cached | Not cached |
fetch() requests | force-cache | no-store |
Client Router Cache (staleTime) | 30 seconds | 0 seconds |
GET Route Handlers:
// v15 -- NOT cached by default. Opt in:
export const dynamic = "force-static";
export async function GET() {
const data = await fetchFromDB();
return Response.json(data);
}
fetch() Requests:
// v15 -- not cached by default. Explicit caching:
const data = await fetch("https://api.example.com/data", {
cache: "force-cache",
});
// Time-based revalidation
const data = await fetch("https://api.example.com/data", {
next: { revalidate: 3600 },
});
// Tag-based revalidation
const data = await fetch("https://api.example.com/data", {
next: { tags: ["products"] },
});
Client Router Cache -- restore v14 behavior:
// next.config.ts