Next.js 16: Dynamic by Default, Turbopack Stable, proxy.ts
Explicit caching with 'use cache', Turbopack as default bundler, and proxy.ts for Node.js runtime clarity
Next.js 16 shifts from implicit to explicit caching, defaults to Turbopack for 2-10× faster builds, and introduces proxy.ts to clarify network boundaries. This release prioritizes predictability over magic—caching is opt-in, bundler choice is transparent, and AI-assisted debugging becomes standard in development.
Paradigm Shift: Dynamic by Default
Previous Next.js versions aggressively cached pages, components, and fetch responses automatically. Next.js 16 executes all dynamic code at request time by default. You must explicitly opt-in to caching with the new "use cache" directive:
// Next.js 15: Implicitly cached
export default function Page() {
const data = await fetch('https://api.example.com/posts');
return <PostList data={data} />;
}
// Next.js 16: Dynamic unless you cache
'use cache'; // Opt-in to caching
export default function Page() {
const data = await fetch('https://api.example.com/posts');
return <PostList data={data} />;
}This aligns Next.js with traditional full-stack frameworks (Rails, Django, Laravel) where every request runs fresh unless you explicitly cache. Learn more about "use cache" and Cache Components.
Five Major Features
1. Cache Components with "use cache"
Fine-grained caching for pages, components, and functions. Supports cacheLife profiles for stale-while-revalidate patterns:
'use cache';
export const cacheLife = 'default'; // 15min stale, 1day revalidate
export async function UserProfile({ id }) {
const user = await db.users.findById(id);
return <Profile user={user} />;
}Requires cacheComponents: true in next.config.ts. Completes Partial Pre-Rendering (PPR) by letting you cache specific parts while keeping others dynamic.
2. Turbopack: Now Stable Default
Turbopack replaces Webpack as the default bundler with measurable performance gains:
- 2–5× faster production builds
- Up to 10× faster Fast Refresh during development
- File system caching (beta): Stores compiler artifacts between runs for even faster restarts
// Opt back to Webpack if needed
// package.json
{
"scripts": {
"dev": "next dev --webpack",
"build": "next build --webpack"
}
}Deep dive into Turbopack performance characteristics.
3. proxy.ts Replaces middleware.ts
New file clarifies network boundaries by running on Node.js runtime (not Edge) with full filesystem and library access:
// proxy.ts
export default function proxy(request: NextRequest) {
// Full Node.js APIs available
const db = require('database-lib');
if (!request.headers.get('authorization')) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}middleware.ts remains available for Edge runtime scenarios but is deprecated. Learn when to use proxy.ts vs middleware.ts.
4. Next.js DevTools MCP
AI-assisted debugging via Model Context Protocol integration:
- Unified browser + server logs in AI chat context
- Automatic error stack trace analysis
- Route-aware debugging (knows which page/API route you're on)
- Compatible with Claude, ChatGPT, and other AI assistants
5. Enhanced Routing & Prefetching
Two critical performance improvements:
- Layout deduplication: Shared layouts download once across multiple prefetches (50 product links = 1 layout download, not 50)
- Incremental prefetching: Only retrieves uncached data, cancels requests when links leave viewport, reprioritizes on hover/click
See incremental prefetching edge cases and debugging strategies.
Breaking Changes That Matter
Async Request APIs
All request-context APIs now require await:
// Next.js 15: Synchronous access
export default function Page({ params, searchParams }) {
const id = params.id;
const query = searchParams.q;
}
// Next.js 16: Must await
export default async function Page({ params, searchParams }) {
const { id } = await params;
const { q } = await searchParams;
}
// Also applies to:
const cookieStore = await cookies();
const headersList = await headers();Parallel Routes Require default.js
Explicit default.js files now mandatory in all parallel route slots to handle navigation fallbacks:
// app/@modal/default.js (required)
export default function Default() {
return null; // Render nothing when modal isn't active
}Removed Features
- AMP support: Completely removed (use React Server Components instead)
- next lint command: Use ESLint or Biome directly
- serverRuntimeConfig/publicRuntimeConfig: Replaced by environment variables
- Node.js 18 support: Requires Node.js 20.9+ and TypeScript 5.1+
New Caching APIs
revalidateTag() with cacheLife
import { revalidateTag } from 'next/cache';
// Now requires cacheLife profile for stale-while-revalidate
await revalidateTag('blog-posts', 'max'); // 'default' | 'max' | custom profileupdateTag() for Read-Your-Writes
New Server Action API that expires cache and immediately refreshes data in the same request:
import { updateTag } from 'next/cache';
export async function updateUserSettings(formData) {
await db.users.update(formData);
// Expire cache and fetch fresh data immediately
await updateTag('user-settings');
// User sees updated data without page refresh
}refresh() for Partial Updates
Server Action that refreshes uncached data only (dynamic elements like notification counts):
import { refresh } from 'next/cache';
export async function checkNotifications() {
await refresh(); // Refreshes dynamic parts, keeps cached parts
}React 19.2 + Canary Features
Next.js 16 ships with React 19.2 and enables experimental canary features:
- View Transitions: Animated element updates between navigations
- useEffectEvent(): Extract non-reactive logic from Effects without re-running on every dependency change
- Activity component: Background state management for long-running operations
Upgrade Strategy
# Automated codemod
npx @next/codemod@canary upgrade latest
# Manual upgrade
npm install next@latest react@latest react-dom@latestKey Migration Steps
- Audit caching behavior: Previously cached pages now run dynamically. Add
"use cache"to pages that should remain cached. - Update async APIs: Wrap
params,searchParams,cookies(),headers()withawait. - Test Turbopack: Should work transparently, but test critical build/deploy pipelines. Opt back to Webpack if needed.
- Migrate middleware.ts: Rename to
proxy.tsor keep if using Edge runtime. - Add default.js to parallel routes: Required for all parallel route slots.
Next.js 16 represents a philosophical shift: predictability over convenience. Dynamic by default, cache explicitly, and always know which runtime your code executes in.
Advertisement
Explore these curated resources to deepen your understanding
Official Documentation
Next.js 16 Release Notes
Official Next.js 16 announcement with complete feature breakdown
Next.js Caching Documentation
Updated caching documentation covering use cache directive
Turbopack Documentation
Official Turbopack documentation and configuration guide
Next.js Upgrade Guide
Step-by-step guide to upgrading from Next.js 15 to 16
Tools & Utilities
Related Insights
Explore related edge cases and patterns
Advertisement