How Prefetching Works in Next.js and How to Control It

Next.js fetches a route's data ahead of a click so navigation feels instant. Learn when prefetching triggers, what it caches, and how to turn it off.

7 min read

Prefetching is Next.js fetching a route's data before a reader clicks the link that leads there, so the actual click only has to render content that already arrived. This is why navigating between pages in a production Next.js app often feels instant instead of showing a loading spinner.

App.tsxApp.tsx
// app/page.tsx
import Link from "next/link";
 
export default function HomePage() {
  return <Link href="/pricing">View pricing</Link>;
}

Deploy this to production and scroll the pricing link into view. Next.js starts fetching that route's data in the background right away, well before any click happens. By the time a reader actually clicks, the content Next.js already fetched is what renders.

What triggers a prefetch

A link entering the browser's viewport is the main trigger, which is why a link far down a long page does not prefetch until the reader actually scrolls to it. Hover mostly matters as a retry: if a route's prefetched data has already gone stale by the time a reader hovers over its link, Next.js prefetches it again at that point.

Prefetching only runs in a production build. During local development, links still navigate correctly, but nothing gets fetched ahead of the click, so this behavior is easy to miss until a project is deployed.

How much of a route gets prefetched

How much data actually gets sent ahead of time depends on the route.

Route typeWhat prefetches
Static routeThe full route
Dynamic route with a loading fileEverything down to that loading boundary
Dynamic route with no loading fileLittle or nothing, since there is no safe static part

Whatever gets prefetched is stored in an in-memory cache in the browser, so a click on an already-prefetched link reuses that data instead of asking the server again. That cache is also what eventually goes stale and triggers the hover-based retry mentioned earlier.

Turning prefetching off

Set prefetch={false} on a link that should not fetch ahead of a click, such as a rarely visited route or one that is expensive to render speculatively.

App.tsxApp.tsx
// app/nav.tsx
import Link from "next/link";
 
export default function Nav() {
  return <Link href="/admin/reports" prefetch={false}>Reports</Link>;
}

This link now only fetches its route's data once the reader actually clicks it, the same as a route that has not been prefetched yet. To trigger a prefetch from code instead of a rendered link, useRouter also exposes a prefetch method. For the deeper version of this behavior under Cache Components, see Partial Prefetching and Instant Navigation in Next.js 16. For the full list of props a link accepts, read The Next.js Link Component: Props and Behavior Explained.

Rune AI

Rune AI

Key Insights

  • Prefetching mainly triggers when a Link scrolls into the viewport, in production only.
  • A static route prefetches in full, a dynamic route only down to its loading boundary.
  • The prefetched data lives in an in-memory client cache until it goes stale.
  • Set prefetch to false on a Link to stop it from prefetching automatically.
  • router.prefetch lets code fetch a route ahead of time outside of rendering a Link.
RunePowered by Rune AI

Frequently Asked Questions

Does prefetching happen while running the local dev server?

No. Prefetching only runs in a production build. In local development, links navigate normally but nothing is fetched ahead of a click.

Does prefetching fetch the entire page every time?

It depends on the route. A static route prefetches in full. A dynamic route without a loading file often prefetches nothing at all, since there is no safe static part to send ahead of time.

How do I turn off prefetching for one link?

Pass prefetch={false} to that Link. Next.js will only fetch the route once the reader actually clicks it.

Conclusion

Prefetching lets Next.js fetch a route's data before a reader clicks it, so the click itself only has to swap in content that is already in the browser. It runs only in production, triggers mainly when a link enters the viewport, and can be turned off per link when a route is rarely visited or too expensive to fetch speculatively.