Back to Blog
Web DevJan 2026·8 min read

Next.js 15 Features Every Developer Should Use

Exploring the most impactful features in Next.js 15 and how to leverage them for better performance.

A
ATmega Team

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.

typescript
// 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.

typescript
// 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.

Ready to Build Something Intelligent?

Talk to our team about turning these ideas into production-ready software for your business.

Start a Conversation