Upgrade to Next.js 16
Next.js 16 (GA October 21, 2025; 16.2.x as of mid-2026) is the current Active LTS. The headline breaking changes are the fully-removed synchronous request APIs, Turbopack as the default bundler, the middleware-to-proxy rename, the new revalidateTag(tag, profile) signature, and a Node.js 20.9+ floor.
Last verified · Updated May 22, 2026
Next.js 16 went GA on October 21, 2025 and is the current Active LTS (16.2.x as of mid-2026). For apps already on 15 the upgrade is moderate: the @next/codemod upgrade CLI handles the version bump, the turbopack config move, the next-lint-to-ESLint migration, the middleware-to-proxy rename, and unstable_ prefix removal. The manual work concentrates in awaiting the now fully-removed sync request APIs, adding a cacheLife profile to revalidateTag(), and confirming Turbopack builds cleanly.
Who should upgrade
- Apps on 15 that want React 19.2, stable Turbopack builds, and the new explicit caching model (Cache Components / use cache).
- Teams that already migrated off synchronous request APIs in 15 (the sync shim is gone in 16).
- Anyone on 14 or earlier — but reach 15 first, then take the 15-to-16 step.
Who should wait
- Apps that depend on the edge runtime for middleware (proxy is Node.js-only today; keep middleware for edge for now).
- Apps pinned to Node.js 18 — 16 requires Node 20.9+.
- Apps relying on the experimental PPR canary behavior — stay on your current 15 canary and follow the Cache Components migration guide.
- Apps with a critical dependency that injects a webpack config you cannot remove and cannot run under Turbopack.
What changed
- Sync request APIs are fully removed: cookies(), headers(), draftMode(), params, and searchParams must be awaited (the 15 warning shim is gone).
- Turbopack is the default bundler for next dev and next build; next build fails if a webpack config is detected (opt out with --webpack).
- middleware.ts is deprecated and renamed to proxy.ts (Node.js runtime only); config flags like skipMiddlewareUrlNormalize become skipProxyUrlNormalize.
- revalidateTag(tag) is deprecated and errors in TypeScript — pass a cacheLife profile, e.g. revalidateTag('posts', 'max'); new updateTag() and refresh() add read-your-writes and uncached-refresh.
- Minimums: Node.js 20.9+, TypeScript 5.1+, React 19.2 in the App Router.
- Removed: AMP, next lint, serverRuntimeConfig/publicRuntimeConfig, devIndicators options, experimental.ppr/dynamicIO/useCache, unstable_rootParams; parallel-route slots now require default.js.
- next/image defaults changed (minimumCacheTTL 4h, qualities [75], imageSizes drops 16, local-IP blocked, max 3 redirects).
- The @next/codemod upgrade CLI automates the version bump plus the turbopack/lint/proxy/unstable_/ppr migrations.
⚠ The sync request-API shim from 15 is gone
Code that read cookies(), headers(), params, or searchParams synchronously only warned in 15. In 16 it no longer works at all. Audit and await every one of these before shipping, and run
npx next typegento generate the PageProps/LayoutProps/RouteContext type helpers.
Recommended upgrade path
Fast path for apps already on 15
# 1. Run the official upgrade CLI (bumps deps + applies the 16 codemods)
npx @next/codemod@canary upgrade latest
# 2. Generate async params/searchParams type helpers
npx next typegen
# 3. Typecheck + build (Turbopack is the default)
npx tsc --noEmit && npm run buildCompatibility matrix
| Concern | Next.js 15 | Next.js 16 |
|---|---|---|
| Sync cookies()/headers()/params | Warns (temporarily allowed) | Removed — must await |
| Default bundler | webpack (Turbopack opt-in via --turbopack) | Turbopack (opt out with --webpack) |
| Request interception file | middleware.ts (edge or node) | proxy.ts (Node.js only); middleware deprecated |
| revalidateTag() | revalidateTag(tag) | revalidateTag(tag, profile) — single-arg errors |
| Minimum Node.js | 18.18+ | 20.9+ |
| React (App Router) | React 19 | React 19.2 |
| next lint | Available | Removed — use ESLint/Biome directly |
| PPR | experimental.ppr / experimental_ppr | cacheComponents + use cache |
AI-assisted migration workflow
Upgrade this app to Next.js 16. First confirm Node 20.9+ and TypeScript 5.1+, then inspect for any remaining synchronous request-API access (cookies/headers/draftMode/params/searchParams), a middleware file, a custom webpack config, and revalidateTag() calls. Run `npx @next/codemod@canary upgrade latest` and `npx next typegen`, await all request APIs, finish the middleware-to-proxy rename, move experimental.turbopack to top-level and drop --turbopack from scripts, add a cacheLife profile to revalidateTag() (or switch to updateTag), add default.js to parallel-route slots, and remove AMP/runtime-config/devIndicators usage. Run typecheck, lint, build (Turbopack), and tests after each step and report before continuing.Safety: Incremental edits only. Pause for review after the codemod, after the proxy rename, and after each caching decision. Keep middleware (not proxy) if you genuinely need the edge runtime.
PR review checklist
- Node.js is 20.9+ and TypeScript is 5.1+ in CI and engines
- next, react (19.2), and react-dom are on compatible versions
- All cookies(), headers(), draftMode(), params, and searchParams access is awaited
- middleware.ts renamed to proxy.ts (function + config flags), or intentionally kept for edge
- Turbopack build passes; --webpack only present if a webpack config is intentionally retained
- revalidateTag() calls pass a cacheLife profile, or use updateTag() in Server Actions
- Parallel-route slots each have a default.js
- No AMP, next lint, serverRuntimeConfig/publicRuntimeConfig, or experimental ppr/dynamicIO usage remains
Rollback strategy
- Keep the dependency bump, codemod, proxy rename, and manual fixes in separate commits.
- Revert to the prior next/react/react-dom versions and reinstall if a blocking incompatibility appears.
- If a webpack-only dependency blocks the Turbopack default, fall back to
next build --webpackrather than reverting the whole upgrade. - Hold the upgrade behind a release branch until the full test suite and next build are green on Node 20.9+.
Common errors
- 'cookies()/headers()/searchParams should be awaited' — now a hard failure; await the async request API.
- 'webpack is configured while Turbopack is not' / build fails on webpack config — run with --webpack or migrate the config.
- TypeScript error on revalidateTag(tag) — add a cacheLife profile second argument.
- Build fails on a parallel route — add default.js to each @slot.
- 'Cannot find module next/amp' or next lint errors — those features are removed in 16.
Related migration paths
- Next.js 13 to Next.js 15 Migration Guide — Related version path
- Next.js 14 to Next.js 15 Migration Guide — Related version path
- Next.js 15 to Next.js 16 Migration Guide — Upgrade path to same target
- Migrate Next.js Pages Router to App Router — Earlier step in the upgrade chain
- Upgrade to Next.js 15 — Related version path
- Fix Next.js Build Errors — Earlier step in the upgrade chain
Official sources
- Next.js 16 — nextjs.org (reliability 98%)
- Upgrading: Version 16 — nextjs.org (reliability 98%)
- Next.js releases — vercel/next.js (reliability 92%)
- Next.js Support Policy — nextjs.org (reliability 98%)
Copy-ready AI prompts
Structured prompts for an AI coding assistant. Inspect first, then execute incrementally, and keep a human in the review loop.
Repo inspection: Repo inspection prompt (Next.js 16)
You are helping migrate a Next.js codebase from nextjs-15 to nextjs-16.
Do not edit files yet. First inspect the repository and report:
1. The exact next, react, and react-dom versions in package.json and the lockfile, plus the Node.js version (16 requires Node 20.9+) and TypeScript version (requires 5.1+).
2. Any remaining synchronous access to cookies(), headers(), draftMode(), params, or searchParams — these are FULLY removed in 16 and must be awaited. Also check params/id in opengraph-image/twitter-image/icon/apple-icon/sitemap generators.
3. A middleware.ts/middleware.js file and any config flags like skipMiddlewareUrlNormalize (these become proxy.ts and skipProxyUrlNormalize; note that proxy does not support the edge runtime).
4. A custom webpack config in next.config (Turbopack is the default in 16 and next build fails if a webpack config is detected) and any experimental.turbopack config to move to top-level.
5. revalidateTag() calls (now require a cacheLife profile second argument), and any unstable_cacheLife/unstable_cacheTag imports.
6. Usage of removed features: AMP (useAmp/next/amp/amp config), next lint, serverRuntimeConfig/publicRuntimeConfig, devIndicators.appIsrStatus/buildActivity, experimental.ppr/dynamicIO/useCache, unstable_rootParams, parallel-route slots missing default.js.
7. next/image config (minimumCacheTTL, qualities, imageSizes, domains) and any local image src using query strings.
8. The build, lint, and test commands.
Return: a migration risk summary, the files most likely to break, a suggested migration order, the commands to run before editing, and any questions that need human confirmation.Safety: Inspection only. The agent must not modify files in this step.
Works with Claude Code, Cursor, GitHub Copilot.
Migration execution: Migration execution prompt (Next.js 16)
Migrate this codebase from nextjs-15 to nextjs-16, one concern at a time.
Work in this order and pause for review after each: (1) confirm Node 20.9+ and TypeScript 5.1+, then bump next, react, and react-dom to latest, (2) run the official upgrade codemod (npx @next/codemod@canary upgrade latest), which updates the turbopack config, migrates next lint to the ESLint CLI, renames middleware to proxy, removes unstable_ prefixes, and drops experimental_ppr, (3) await every remaining synchronous request API (cookies/headers/draftMode/params/searchParams) — sync access is fully removed in 16; run `npx next typegen` for PageProps/LayoutProps/RouteContext helpers, (4) finish the middleware to proxy rename (function name + config flags) unless you must keep the edge runtime, (5) handle Turbopack as default — remove --turbopack from scripts, move experimental.turbopack to top-level turbopack, and only add --webpack if you must keep a webpack build, (6) add a cacheLife profile to revalidateTag() calls (or switch to updateTag in Server Actions), (7) fix removed config (AMP, runtime config, devIndicators, ppr/dynamicIO) and add default.js to parallel-route slots, (8) review next/image config defaults, (9) fix type errors.
After each step run the project's typecheck, lint, build, and tests, and report results before continuing. Do not refactor unrelated code.Safety: Apply changes incrementally and keep each step reviewable. Never bundle unrelated refactors.
Works with Claude Code, Cursor, GitHub Copilot.
Test plan
Commands
node -v # must be >= 20.9.0npx tsc --noEmitnpm run lintnpm test -- --watch=falsenpm run build
Manual checks
- Dynamic routes: load pages reading params/searchParams and confirm they await cleanly (sync access no longer compiles/runs).
- Auth/session: exercise routes using cookies() and headers() after awaiting them.
- Proxy: confirm renamed proxy.ts runs request interception identically to the old middleware (note: Node.js runtime only).
- Bundler: run next build with Turbopack (the default) and confirm output is correct; verify --webpack only if you intentionally kept webpack.
- Caching: confirm revalidateTag()/updateTag() invalidation behaves as intended after adding cacheLife profiles.
- Parallel routes: every @slot has a default.js and the build no longer fails.
- Images: spot-check next/image rendering given the new qualities/minimumCacheTTL/imageSizes defaults.
Regression risks
- Synchronous request-API access that compiled with a warning in 15 now hard-failing in 16.
- next build failing because a dependency injects a webpack config under Turbopack-by-default.
- Request interception silently broken if proxy.ts is created but the edge runtime was actually required.
- Stale caches because revalidateTag() lost its single-argument behavior and needs a cacheLife profile.
- Builds failing on parallel-route slots that lack default.js.
Acceptance criteria
- Typecheck, lint, tests, and next build (Turbopack) all pass on Node 20.9+.
- No synchronous request-API access remains anywhere in the app.
- middleware is renamed to proxy (or intentionally kept for edge), and revalidateTag() calls specify a cacheLife profile.
Frequently asked questions
Is Next.js 16 a hard upgrade from 15?
For most 15 apps it is moderate. The @next/codemod upgrade CLI handles the dependency bump, the Turbopack config move, the next-lint-to-ESLint migration, the middleware-to-proxy rename, and unstable_ prefix removal. The manual effort is mostly awaiting the now fully-removed sync request APIs and adding a cacheLife profile to revalidateTag().
Do I have to switch to Turbopack?
Turbopack is the default in 16 for both next dev and next build. If you have a custom webpack config, next build fails by default; you can keep webpack with the --webpack flag, migrate the config to Turbopack options, or run Turbopack anyway. Vercel recommends Turbopack for development and production.
What happened to middleware.ts?
It is deprecated and renamed to proxy.ts, with the exported function renamed to proxy. proxy runs on the Node.js runtime only; if you rely on the edge runtime, keep using middleware.ts for now. The v16 codemod can perform the rename and update related config flags.