Next.js 15 shipped with a set of changes that fundamentally alter how you reason about caching, data fetching, and Server Components. If you have been building Next.js applications for a while, some of these represent a genuine paradigm shift — not just incremental improvements.
Async Request APIs
The biggest breaking change in Next.js 15 is the move to async request APIs. `cookies()`, `headers()`, `params`, and `searchParams` are now all async and must be awaited. This aligns them with the dynamic nature of request-time data and enables better static analysis by the build system.
In practice, this means updating your layouts and pages to `async` functions and awaiting these values. The Next.js codemod handles most of the migration automatically.
// Before (Next.js 14)
const cookieStore = cookies();
const token = cookieStore.get('token');
// After (Next.js 15)
const cookieStore = await cookies();
const token = cookieStore.get('token');Caching Changes — Fetch Is No Longer Cached by Default
In Next.js 14, `fetch` requests were cached by default. This confused many developers who expected live data but received stale cached responses. Next.js 15 reverses this default: `fetch` requests and `GET` route handlers are no longer cached by default.
You now opt into caching explicitly. This is a more intuitive default that reduces unexpected behaviour in production.
// Opt into caching explicitly
const data = await fetch('https://api.example.com/data', {
next: { revalidate: 3600 } // cache for 1 hour
});
// Or always fresh
const data = await fetch('https://api.example.com/data', {
cache: 'no-store'
});Partial Prerendering (Stable)
Partial Prerendering (PPR) allows a single route to combine static and dynamic rendering. The static shell is served instantly from CDN while dynamic holes are streamed in. The result is near-instant page loads even for pages with personalised or real-time content.
Enable it per-route with `experimental_ppr = true` (now stable in Next.js 15). Wrap your dynamic components in `<Suspense>` to define the boundaries.
Turbopack Stable for Development
Turbopack is now stable for `next dev`. For large codebases, fast refresh times in development are significantly improved over the old Webpack-based pipeline. Turbopack's incremental architecture means only changed modules are recompiled.
If you have been holding off on Turbopack due to plugin incompatibilities, now is the time to re-evaluate. The ecosystem support has matured substantially.
React 19 Support
Next.js 15 ships with full React 19 support, bringing native `use()` hook support, improved Server Actions, and the new `<Form>` component that provides client-side navigation with form submissions out of the box.
The React 19 `use()` hook is particularly useful for reading promises and context values in components — it works in both server and client components and integrates cleanly with Suspense.