Skip to the solution
MediumFrontend10 min read

What breaks when you upgrade to Next.js 16, and how do you migrate?

907 views

The problem

Question presented to candidate: "We run a Next.js 15 App Router app in production. Management wants us on 16 this sprint. Walk me through what will break, in what order you would tackle it, and how you would know the upgrade is actually done."

What a strong answer should cover:

  • Requirements: Node.js 20.9+, TypeScript 5.1+, current react/react-dom and their types; Turbopack becomes the default for next dev and next build, and a custom webpack config with no turbopack config fails the build.
  • Removals: synchronous params, searchParams, cookies(), headers() and draftMode(); next lint and the eslint config key; AMP; serverRuntimeConfig and publicRuntimeConfig; experimental.ppr, experimental.dynamicIO and unstable_rootParams.
  • Renames and new defaults: middleware.ts becomes proxy.ts (Node.js runtime), revalidateTag needs a second argument, parallel route slots need default.js, and next/image gets stricter defaults.
  • Process: run npx @next/codemod@canary upgrade latest (plus the async request API codemod if needed), then fix what the build and type check report, then test runtime behaviour, because some breakages are silent.
  • 16.4 adds next upgrade --agent, which prepares the version guides and hands the migration to a coding agent.

Clarifying questions expected:

  • "Do we use a custom webpack config, edge middleware or AMP?" β€” those are the riskiest items.
  • "Which Next.js 15 minor are we on, and did we adopt PPR canaries?" β€” PPR from 15 canaries has no direct equivalent.

Code / implementation expected: Yes β€” the codemod commands and before/after for async params and the config.

  • nextjs
  • upgrade
  • migration
  • next-16

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

10 min read Β· 8 sections

Read the code

Upgrade commands
# Option A (16.4+): let a coding agent run the upgrade with version-matched guides
npx next@canary upgrade --agent=latest

# Option B: run the codemods yourself
npx @next/codemod@canary upgrade latest
npx @next/codemod@canary next-async-request-api .   # sync params/cookies/headers leftovers
npx @next/codemod@canary middleware-to-proxy .        # included in upgrade, also usable alone
npx @next/codemod@canary next-lint-to-eslint-cli .    # replaces next lint scripts

# Generate PageProps / LayoutProps / RouteContext helpers so the type check catches sync params
npx next typegen
Before and after: params as a Promise
// Before (Next.js 15 style): builds, but renders an empty <h1> on 16
// export default function Page({ params }: { params: { slug: string } }) {
//   return <h1>{params.slug}</h1>;
// }

// After: typed with the generated helper and awaited
export default async function Page(props: PageProps<"/blog/[slug]">) {
  const { slug } = await props.params;
  return <h1>{slug}</h1>;
}
next.config.ts after the upgrade
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // eslint, serverRuntimeConfig, publicRuntimeConfig, amp and experimental.ppr removed
  images: {
    remotePatterns: [{ protocol: "https", hostname: "images.example.com" }], // was images.domains
  },
  skipProxyUrlNormalize: true, // was skipMiddlewareUrlNormalize
};

export default nextConfig;

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 42 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextMedium

App Router 15 β€” why are params and searchParams now Promises?

Continue