Blog / 01

Next.js 16.3: Instant Navigations & Partial Prefetch

WebRestart

Next.js 16.3 is almost here, and its headline feature tackles the oldest complaint about Server Components: navigations that feel slow. The 16.3 Preview ships Instant Navigations, a suite of opt-in tools that give server-driven apps the snappy, single-page-app feel — without giving up the server-centric model.

If you have ever clicked a link in a Next.js app and stared at an unchanged screen while the server thought about it, this release is for you.

The problem it solves

In a server-driven app, a navigation usually costs a network roundtrip:

  1. You click a link.
  2. Nothing happens.
  3. The server responds, and the next page appears.

That is fine for a blog or a newspaper. It is not fine for an app that should feel like software. SPAs win here because they show a shell of the next page instantly, then fill in the data. Next.js 16.3 lets you have both: the benefits of the server, with navigations that feel instant.

Stream, Cache, or Block

Everything starts with the Cache Components flag:

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

const nextConfig: NextConfig = {
  cacheComponents: true,
};

export default nextConfig;

With it enabled, whenever a route awaits data on the server, Next.js asks you to make a choice about that navigation:

Stream

Wrap the slow part in <Suspense>. The user instantly sees a loading state, and the rest streams in after. The navigation feels instant.

Cache

Mark the work with 'use cache'. The user instantly sees a previously cached UI, reused between requests. Also instant.

Block

Sometimes you want a navigation to wait for the server — a blog post that should never flash a loading shell, for example. Opt out per route:

// page.tsx or layout.tsx
export const instant = false;

The point is that you stay in control. Stream or Cache when you want instant; Block when you want the server to have the last word.

Rethinking prefetching

Instant rendering is only half the battle. For a click to feel instant, the client also has to already know the response by the time the user clicks — which means prefetching.

Until now, Next.js prefetched a request for every link in the viewport. A sidebar with twenty chat links fired twenty prefetch requests, even though they all pointed at the same /chat/[id] route. As the team put it:

Many of you told us that this looked ridiculous, and frankly, we agree.

16.3 borrows the SPA trick instead. Next.js now prefetches one reusable shell per route, not per link, and caches it on the client so it is only fetched once. Twenty chat links share a single /chat/[id] shell. This is Partial Prefetching, and it is a separate flag:

// next.config.ts
const nextConfig: NextConfig = {
  cacheComponents: true,
  partialPrefetching: true,
};

Need more than a shell for a specific link? Opt back into deeper prefetching with <Link prefetch> combined with 'use cache' — no more all-or-nothing choice. Because shells are reused across links, they also lay the groundwork for offline navigation in a future release.

Tooling to keep it fast

The best part is that slow navigations no longer hide in production:

  • Instant Insights turns a slow navigation into a development error, pointing you straight at the route that blocks.
  • The Navigation Inspector in Next.js DevTools lets you pause any navigation at the shell so you can see exactly what gets prefetched, then Resume to reveal the full page.
  • An instant() test helper for Playwright lets you assert what must be visible immediately after a click, so regressions get caught in CI:
import { expect, test } from '@playwright/test';
import { instant } from '@next/playwright';

test('product title is available immediately', async ({ page }) => {
  await page.goto('/products/shoes');

  await instant(page, async () => {
    await page.click('a[href="/products/hats"]');
    await expect(page.locator('h1')).toContainText('Baseball Cap');
    await expect(page.getByText('Checking inventory...')).toBeVisible();
  });

  await expect(page.getByText('12 in stock')).toBeVisible();
});

Vercel has been dogfooding all of this on v0, using Instant Insights to hunt down the routes that were not navigating instantly.

Try it today

Both features are gated behind cacheComponents: true and partialPrefetching: true, and are available now in the preview channel:

npm install next@preview

There is an open-source demo, Next Beats, a music player built on the 16.3 Preview if you want to see the patterns in a real codebase. Expect these behaviors to become the default in a future major release, so adopting them now is a head start, not throwaway work.

Full details are in the official announcement.


Planning a Next.js upgrade or a performance-first rebuild? Get in touch — we help teams ship fast, server-driven apps that still feel instant.