Next.js Is Rethinking Prefetching, and It Is About Time
If you have ever opened the Network tab on a production Next.js app and watched it fire a separate prefetch request for every single link that scrolled into view, this post is the one you have been waiting for. Vercel's framing is blunt about it: many of you told us this looked ridiculous, and frankly, we agree.
Next.js 16.3: Instant Navigations
Partial Prefetching, Instant Insights, and a reusable loading shell per route.
The fix borrows the one genuinely good idea from single-page apps. Instead of prefetching per link, Next.js now prefetches a reusable shell per route and caches it on the client for the session. A sidebar with twenty chat links used to mean twenty requests; now it means one, for the /chat/[id] route, reused across all of them. It is the same mental model as per-route code splitting, applied to data fetching.
The other half is a diagnostic rather than an optimization, and I suspect it will change more codebases than the prefetching does. Slow navigations become an actual error in development. When a route awaits data, you are pushed to pick one of three options: Stream it with <Suspense>, Cache it with 'use cache', or explicitly opt out with export const instant = false. That last one matters, because "this route should block" is a legitimate choice for a blog post, and being made to state it out loud is better than having it happen by accident. There is also an instant() Playwright helper so you can assert what must be visible before the network resolves, which is the first time I have seen a framework ship a test primitive for perceived performance.
I am staying on stable 16.2 here for now, partly because this site is almost entirely static and gets very little out of smarter prefetching. But the direction is right, and the honesty about the old behaviour is refreshing. The framework spent a couple of years insisting the prefetch flurry was fine, and it is genuinely good to see that walked back rather than defended.