Skip to main content
Back to blog

What's new in Next.js 16: proxy.ts, Turbopack, and Cache Components

Ray MartínRay Martín
11 min read
What's new in Next.js 16: proxy.ts, Turbopack, and Cache Components

Next.js 16 is a major release that brings Turbopack as the default bundler, replaces middleware with proxy.ts, introduces Cache Components, and makes all request APIs async. If you're upgrading from Next.js 15, this guide covers every breaking change and new feature you need to know.

proxy.ts replaces middleware.ts

The biggest naming change in Next.js 16 is that middleware.ts is now proxy.ts. The function also runs on the full Node.js runtime (not Edge), giving you access to the entire Node.js API:

typescript
// proxy.ts (at the same level as app/)
import { NextRequest, NextResponse } from 'next/server';

export function proxy(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // Locale detection with full Node.js available
  const locale = detectLocale(request);

  // Redirect if no locale prefix
  if (!pathname.startsWith('/es') && !pathname.startsWith('/en')) {
    return NextResponse.redirect(
      new URL(`/${locale}${pathname}`, request.url)
    );
  }

  return NextResponse.next();
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

Key differences from middleware.ts

  • Full Node.js runtime: You can use node:fs, node:crypto, ORMs, and any npm package — no more Edge runtime restrictions.
  • File location: Place proxy.ts at the same level as your app/ directory. If you use src/, it goes inside src/.
  • Same API: The function signature, NextRequest/NextResponse, and matchers work identically.
  • Migration: Rename middleware.ts to proxy.ts and update the export name from middleware to proxy.

Turbopack is the default bundler

Turbopack is now the default bundler in Next.js 16, replacing Webpack. It's written in Rust and delivers dramatically faster build times:

  • Cold start: ~0.8s vs ~4.2s with Webpack (5x faster)
  • HMR (Hot Module Replacement): ~15ms vs ~320ms (20x faster)
  • Production build: ~12s vs ~45s for a medium-size app (4x faster)
  • Scales with app size: HMR speed doesn't degrade as your app grows.

Configuration

Turbopack configuration is now top-level in next.config.ts — no longer under experimental:

typescript
// next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  // Turbopack config is now top-level
  turbopack: {
    rules: {
      '*.svg': {
        loaders: ['@svgr/webpack'],
        as: '*.js',
      },
    },
    resolveAlias: {
      // Custom module resolution
    },
  },
};

export default nextConfig;

If you had experimental.turbopack in your config, simply move it to the top level.

Async Request APIs

All request-scoped APIs are now async in Next.js 16. This is a breaking change that affects every component and route handler that uses these functions:

typescript
// Before (Next.js 15)
const cookieStore = cookies();
const headersList = headers();
const { id } = params;
const { q } = searchParams;

// After (Next.js 16)
const cookieStore = await cookies();
const headersList = await headers();
const { id } = await params;
const { q } = await searchParams;

Automated migration

Next.js provides a codemod to automate this migration:

bash
# Run the async APIs codemod
npx @next/codemod@latest next-async-request-api .

This will find all usages of cookies(), headers(), params, and searchParams and add await where needed.

Examples in practice

tsx
// app/[locale]/page.tsx
export default async function HomePage({
  params,
}: {
  params: Promise<{ locale: string }>;
}) {
  const { locale } = await params;
  // ...
}

// app/api/auth/route.ts
export async function GET() {
  const cookieStore = await cookies();
  const token = cookieStore.get('session')?.value;
  // ...
}

Cache Components with 'use cache'

Cache Components replace the experimental PPR (Partial Prerendering) from Next.js 15. They let you mark specific components or functions as cacheable:

tsx
// A cached Server Component
'use cache';

import { cacheLife, cacheTag } from 'next/cache';

export async function ProductList() {
  cacheLife('hours');       // Cache for 1 hour
  cacheTag('products');     // Tag for targeted invalidation

  const products = await db.product.findMany();

  return (
    <ul>
      {products.map((p) => (
        <li key={p.id}>{p.name} — {p.price}</li>
      ))}
    </ul>
  );
}

Targeted invalidation

typescript
// app/admin/actions.ts
'use server';

import { revalidateTag } from 'next/cache';

export async function updateProduct(id: string, data: ProductData) {
  await db.product.update({ where: { id }, data });

  // Invalidate only components tagged with 'products'
  revalidateTag('products');
}

Other notable changes

Node.js 24 LTS

Next.js 16 defaults to Node.js 24 LTS. Node.js 18 is deprecated. Make sure your CI and deployment environments are updated.

vercel.ts configuration

You can now configure your Vercel project with TypeScript instead of JSON:

typescript
// vercel.ts
import { routes, type VercelConfig } from '@vercel/config/v1';

export const config: VercelConfig = {
  buildCommand: 'npm run build',
  framework: 'nextjs',
  crons: [{ path: '/api/cleanup', schedule: '0 0 * * *' }],
};

cacheHandlers (plural)

The cacheHandler config option was renamed to cacheHandlers (plural) to support multiple handler types.

Migration Checklist

Here's a quick checklist for upgrading from Next.js 15 to 16:

  • Rename middleware.ts to proxy.ts and update the export function name.
  • Run npx @next/codemod@latest next-async-request-api . to add await to all request APIs.
  • Move experimental.turbopack config to top-level turbopack.
  • Replace PPR with Cache Components ('use cache' directive).
  • Rename cacheHandler to cacheHandlers in next.config.ts.
  • Update Node.js to 24 LTS in CI/CD and Docker images.
  • Test all middleware logic under the Node.js runtime (no more Edge restrictions).

Conclusion

Next.js 16 is a significant step forward. Turbopack makes development noticeably faster, proxy.ts removes the Edge runtime limitations of middleware, and Cache Components give you fine-grained control over what gets cached and when. The migration path is well-supported with codemods, so upgrading is straightforward.

Share:

Related articles