Next.js Upgrade Guide

Compare Next.js versions and see exactly what changes, what requires action, and what you can start using.

→
5Changes
1Breaking
5Actions
0Features
1Migration tools
Analyze your project

Check your package.json

UpgradePath detects relevant tools and selects them automatically.

Local only
Analyzed locally in your browser. Nothing is uploaded.
Project setup

What does your project use?

Select the tools in your project to include relevant dependency updates in this guide.

Breaking Changes

Request APIs become asynchronous

Action required
breakinghigh impact

cookies, headers, draftMode, params and searchParams require migration.

Beforetsx
import { cookies } from 'next/headers';
type Props = { params: { slug: string } };
export default function Page({ params }: Props) {
  const theme = cookies().get('theme')?.value;
  return <main data-theme={theme}>{params.slug}</main>;
}
Aftertsx
import { cookies } from 'next/headers';
type Props = { params: Promise<{ slug: string }> };
export default async function Page({ params }: Props) {
  const { slug } = await params;
  const store = await cookies();
  const theme = store.get('theme')?.value;
  return <main data-theme={theme}>{slug}</main>;
}
Migration

Await request APIs and route props in App Router code. Run npx @next/codemod@latest next-async-request-api . and review its output.

Migration Tools

App Router adopts React 19

Action required
migrationmedium impact

React dependencies and types need coordinated updates.

Beforejson
{
  "dependencies": {
    "next": "^14.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}
Afterjson
{
  "dependencies": {
    "next": "^15.0.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  }
}
Migration

Upgrade react and react-dom together. For TypeScript, update their types and check third-party peer dependencies.

Behavior Changes

fetch is uncached by default

Action required
behaviormedium impact

Server fetch calls no longer opt into caching automatically.

Beforetypescript
// Next.js 14: cache-eligible server request
const response = await fetch('https://example.com/api/catalog');
Aftertypescript
// Next.js 15: opt in if this catalog should remain cached
const response = await fetch('https://example.com/api/catalog', {
  cache: 'force-cache',
});
Migration

Use cache: 'force-cache' explicitly where caching is intended; check freshness and SSR performance.

GET Route Handlers are uncached by default

Action required
behaviormedium impact

GET responses no longer default to cached output.

Beforetypescript
// app/api/catalog/route.ts
export async function GET() {
  return Response.json({ categories: ['books', 'music'] });
}
Aftertypescript
// Only for public data intended to be statically cached.
export const dynamic = 'force-static';
export async function GET() {
  return Response.json({ categories: ['books', 'music'] });
}
Migration

Opt eligible handlers into static caching with export const dynamic = 'force-static'.

Page segments are not cached by default

Action required
behaviormedium impact

Client navigation changes page cache reuse.

Beforejavascript
// next.config.mjs
// Next.js 14 page cache defaults
export default {};
Afterjavascript
// Optional: reuse dynamic page segments for 30 seconds.
export default {
  experimental: {
    staleTimes: { dynamic: 30 },
  },
};
Migration

Review navigation and staleTimes configuration; test back/forward behavior.