Next.js 16: What's New, Key Features & How to Upgrade

Lokman Musliu Founder and CEO of Lucky Media
Lokman Musliu

July 28, 2025 · 6 min read

Next.js 16: An early look and release date

Next.js 16 was released on October 21, 2025, at Next.js Conf 2025. The version is stable and powering production applications today. This guide covers everything that actually shipped: Turbopack as the new default bundler for both development and production builds, Cache Components with the "use cache" directive replacing Partial Prerendering (PPR), proxy.ts replacing middleware.ts, three new caching APIs, React 19.2 support, and all breaking changes you need to handle before upgrading.

What is Next.js 16?

Next.js 16 is the latest stable major release of the React framework built by Vercel. The release focuses on three main themes: making caching explicit through Cache Components and the "use cache" directive, promoting Turbopack to the default bundler for production builds, and stabilizing the React Compiler integration. It shipped alongside Next.js Conf 2025 and includes full React 19.2 support.

Turbopack is now the default bundler

Turbopack is now the default bundler for all new Next.js 16 projects created with create-next-app. For projects upgrading from Next.js 15, both next dev and next build now use Turbopack by default.

  • 2–5x faster production builds compared to webpack

  • Up to 10x faster Fast Refresh in development

  • Already used in 50%+ of development sessions on Next.js 15.3+

To opt back to webpack, pass the --webpack flag:

next build --webpack

Turbopack File System Caching (Beta)

Next.js 16 introduces Turbopack File System Caching as a beta feature. It persists compiled artifacts to disk between dev server restarts. For large projects, this eliminates the full re-analysis cost on every cold start — only files that changed since the last session are recompiled.

Enable it in next.config.ts:

const nextConfig = {
  experimental: {
    turbopackFileSystemCacheForDev: true,
  },
}
export default nextConfig

Cache Components — the new caching model

Next.js 16 replaces Partial Prerendering (PPR) and experimental.dynamicIO with a unified system called Cache Components. The experimental.ppr config flag is removed.

The new model is built around the "use cache" directive. Add it to any function, component, or route segment to mark it as cacheable. The compiler generates cache keys automatically based on the function's inputs — no manual key management required.

Enable Cache Components in next.config.ts:

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  cacheComponents: true,
}

export default nextConfig

With Cache Components enabled, mark data-fetching functions with the directive:

export async function getProducts() {
  'use cache'
  const data = await fetch('https://api.example.com/products')
  return data.json()
}

Cache keys are scoped to the function's arguments. Calling getProducts() with different arguments produces separate cache entries automatically.

React Compiler is now stable

The React Compiler is stable in Next.js 16, promoted from the experimental flag in Next.js 15. It analyzes your component code at build time and inserts memoization automatically — eliminating the need to manually write useMemo, useCallback, and React.memo wrappers.

The compiler relies on Babel, which increases build and compilation time. It is opt-in and not enabled by default.

Install the compiler plugin:

npm install babel-plugin-react-compiler@latest

Enable it in next.config.ts:

const nextConfig = {
  reactCompiler: true,
}
export default nextConfig

New and updated caching APIs

updateTag() — new

updateTag() is a new Server Actions-only API that provides read-your-writes cache semantics. After a mutation, call updateTag() to immediately refresh the cache tag for the current user's session. Other users are not affected — their cache stays valid until natural expiry or a revalidateTag() call.

'use server'
import { updateTag } from 'next/cache'

export async function updatePost(id: string, data: FormData) {
  await db.posts.update(id, data)
  updateTag(`post-${id}`)
}

refresh() — new

refresh() is a Server Actions-only API that re-fetches all uncached (dynamic) data on the current page without a full page reload. Use it for dashboards and real-time data views where you want the latest data without a cache tag system.

'use server'
import { refresh } from 'next/cache'

export async function refreshDashboard() {
  refresh()
}

revalidateTag() — breaking change

revalidateTag() now requires a second argument specifying the cacheLife of the tag. Existing calls with a single argument will throw an error in Next.js 16 — update all call sites before upgrading.

// Next.js 15 — no longer valid
revalidateTag('products')

// Next.js 16 — second argument required
revalidateTag('products', 'minutes')

proxy.ts replaces middleware.ts

Next.js 16 deprecates middleware.ts in favor of proxy.ts. The key difference: proxy.ts runs on the Node.js runtime, giving you access to the full Node.js API for request interception, authentication, and redirects. The old middleware was limited to the Edge runtime.

Migration requires two changes:

  • Rename middleware.ts to proxy.ts at the project root

  • Rename the exported function from middleware to proxy

  • The config export with the matcher array stays the same

// middleware.ts — before
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

export const config = {
  matcher: '/about/:path*',
}
// proxy.ts — after
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function proxy(request: NextRequest) {
  return NextResponse.redirect(new URL('/home', request.url))
}

export const config = {
  matcher: '/about/:path*',
}

The original middleware.ts still works for Edge runtime use cases but is deprecated and will be removed in a future major version.

Enhanced routing and navigation

Next.js 16 ships two routing improvements that reduce bandwidth usage. No code changes are required to benefit from either.

Layout deduplication

When navigating between pages that share a layout, the layout is now downloaded once and reused across all navigations. In Next.js 15, navigating across 50 product pages in a category would download the shared layout 50 times. Next.js 16 eliminates this redundancy automatically.

Incremental prefetching

Prefetching is now incremental — the browser requests only the specific route segments needed for the next navigation rather than prefetching entire route bundles. Total data transferred per navigation is reduced, even if the number of individual network requests increases slightly.

React 19.2 features

Next.js 16 ships with React 19.2. The most relevant additions for Next.js developers:

View Transitions API

React 19.2 adds native support for the browser's View Transitions API. Wrap navigation events in React's startTransition() to trigger smooth animated transitions between routes — without JavaScript animation libraries.

useEffectEvent()

useEffectEvent() creates stable event handler functions that always read the latest props and state. Unlike useCallback, the returned function does not need to be included in useEffect dependency arrays, eliminating stale closure bugs.

<Activity/> component

The <Activity/> component keeps a subtree's state alive when it is hidden, without rendering it to the DOM. This is useful for tabs, modals, and route transitions where you want to preserve state without paying the render cost of keeping the component mounted.

Breaking changes — what you need to fix

Review every item in this table before upgrading. The automated codemod handles most of them — run it first, then address any remaining items manually.

Change

What to do

Node.js 18 dropped

Upgrade to Node.js 20.9.0 or higher

TypeScript 5.1+ required

Run npm install typescript@latest

AMP support removed

Remove AMP pages; Next.js no longer generates AMP markup

serverRuntimeConfig and publicRuntimeConfig removed

Use .env files and the NEXT_PUBLIC_ prefix for client-accessible values

Sync params and searchParams access removed

Await params and searchParams in all layouts and pages

Sync cookies(), headers(), draftMode() removed

Await these calls in server components and route handlers

next lint command removed

Use eslint directly or update your package.json lint script

experimental.ppr flag removed

Replace with cacheComponents: true in next.config.ts

Parallel routes require explicit default.js

Add a default.js file to each parallel route slot directory

How to upgrade to Next.js 16

The recommended path is the automated codemod. It handles async Request API migrations and most other breaking changes:

npx @next/codemod@canary upgrade latest

To upgrade manually:

npm install next@latest react@latest react-dom@latest

For a new project:

npx create-next-app@latest

If you are upgrading from Next.js 14, the changes introduced in Next.js 15 are also required reading — particularly the async Request APIs and the caching behavior changes. See: Next.js 15: Full Feature Breakdown and Breaking Changes.


Bring Your Ideas to Life 🚀

If you need help with a Next.js project let's get in touch.

Lucky Media is proud to be recognized as a leading Next.js Development Agency

FAQs

Is Next.js 16 stable?

Yes. Next.js 16 was released on October 21, 2025, at Next.js Conf 2025. It is stable and production-ready.

Do I need to update my code to use Next.js 16?

Yes. Next.js 16 includes several breaking changes. The recommended first step is to run the automated codemod: npx @next/codemod@canary upgrade latest. This handles the most common breaking changes, including async Request API migrations.

Is Turbopack required in Next.js 16?

No. Turbopack is the new default for both development and production builds, but you can opt out by passing the --webpack flag: next build --webpack.

What happened to PPR (Partial Prerendering)?

PPR evolved into Cache Components in Next.js 16. The experimental.ppr config flag is removed. Enable the new system with cacheComponents: true in your next.config.ts file.

What replaces middleware.ts in Next.js 16?

proxy.ts replaces middleware.ts. Rename your file from middleware.ts to proxy.ts and rename the exported function from middleware to proxy. The middleware.ts file still works for Edge-only use cases but is deprecated and will be removed in a future major version.

Technologies

Next.js
Lokman Musliu Founder and CEO of Lucky Media
Lokman Musliu

Founder and CEO of Lucky Media

Stay up-to-date

Be updated with all news, products and tips we share!

Let’s chat

We partner with a limited number of brands each quarter to ensure senior-level attention on every project.

lokman and arlind headshots
Teamwork

Related posts

August 26, 2024

Laravel guide for Next.js developers
Laravel
Next.js