Featured image of post Next.js 15 Stable Release: Best Practices in Production Featured image of post Next.js 15 Stable Release: Best Practices in Production

Next.js 15 Stable Release: Best Practices in Production

Analyzing caching defaults, React 19 stable compatibility, and upgraded dynamic routing paradigms in Next.js 15.

Introduction

Next.js 15 ships as a stable release with React 19 support, a redesigned caching model, and major API improvements for async request handling. This version defaults to no caching for fetch requests and GET Route handlers, simplifying behavior predictability. It also introduces async variants for cookies(), headers(), and params(), aligning with React 19’s async rendering paradigm. This article covers every breaking change and best practice for production adoption.


React 19 Stable Compatibility

Next.js 15 pairs with React 19 stable, enabling the new React Compiler to automatically memoize components and hooks. This eliminates the need for manual useMemo, useCallback, and React.memo in many cases.

To opt into the React Compiler:

// next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
export default nextConfig;

New React 19 APIs like use() (reading promises directly in render) and Server Actions with "use server" are fully supported.


Caching Defaults Changed

In Next.js 14, fetch requests were cached by default. In Next.js 15, fetch requests are not cached by default — you must explicitly opt in:

// Next.js 15 — NOT cached unless specified
const data = await fetch('https://api.example.com/data');

// Opt into caching
const cached = await fetch('https://api.example.com/data', {
  cache: 'force-cache',
});

GET Route Handlers also return dynamic responses by default. To make them static:

// app/api/data/route.ts
export const dynamic = 'force-static';

This change reduces surprise behavior in dynamic applications and aligns with the principle of progressive enhancement.


Async Request APIs: cookies(), headers(), params()

Next.js 15 requires async access for request-time APIs:

// app/dashboard/page.tsx
import { cookies } from 'next/headers';

export default async function Page() {
  const cookieStore = await cookies();
  const token = cookieStore.get('session');
  // ...
}

The same applies to headers():

import { headers } from 'next/headers';

export default async function Page() {
  const headersList = await headers();
  const userAgent = headersList.get('user-agent');
}

And dynamic route params are now async:

// app/blog/[slug]/page.tsx
export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  return <div>Post: {slug}</div>;
}

This change enables better streaming and suspense integration.


Turbopack Improvements

Turbopack, the Rust-based bundler, reaches stable for development in Next.js 15. Key improvements include:

  • 70% faster cold starts compared to webpack
  • Instant Fast Refresh with persistent caching
  • Improved CSS and SVG handling without plugins

Enable it explicitly:

// next.config.ts
const nextConfig = {
  turbopack: true,
};

Other Notable Changes

FeatureNext.js 14Next.js 15
React versionReact 18React 19 + Compiler
fetch cachingDefault cachedDefault uncached
params accessSynchronousPromise-based
cookies()/headers()Synchronousasync functions
Dev bundlerwebpack (default)Turbopack (default)
FormsServer ActionsEnhanced "use server" directives

Migration from Next.js 14

  1. Update packages: npm install next@15 react@19 react-dom@19
  2. Make params async: Change any params usage to await params
  3. Update cookies()/headers(): Add await before each call
  4. Review caching: Add cache: 'force-cache' where caching is needed
  5. Enable Turbopack: Set turbopack: true in next.config.ts
  6. Test React Compiler: Enable reactCompiler: true experimentally

Conclusion

Next.js 15 brings long-awaited stability with React 19, predictable caching defaults, and cleaner async request APIs. The move to Turbopack as the default dev bundler significantly improves iteration speed. While the caching default change may require adding explicit opt-ins, the overall result is a more transparent and performant framework. Teams should plan for the async API migrations but will benefit from reduced configuration overhead and future-proof React 19 integration.