All posts
performanceprefetching

Prefetching Strategies: A Practical Guide for Full-Stack Developers

A practical guide to prefetching — loading data and routes before they're needed, without wasting bandwidth on content users won't visit.

SR

Suhail Roushan

August 6, 2026

·
4 min read
·
0 views

The fastest navigation is one where the destination is already loaded before the user clicks — prefetching trades some bandwidth spent on guesses for navigations that feel instant when the guess is right.

Prefetching loads resources — routes, data, assets — before they're explicitly needed, anticipating what a user is likely to do next. Done well (prefetching a link the user is hovering over, or the next page in a paginated flow), it makes navigation feel instantaneous. Done poorly, it wastes bandwidth prefetching content most users will never actually visit.

Why Prefetching Matters (and When to Skip It)

Waiting until a user clicks a link to start fetching its content means the user experiences that fetch latency directly. Prefetching shifts that cost earlier — often to a moment (hovering, viewport visibility) that reliably precedes an actual navigation — so by the time the user clicks, the content is already loaded or loading.

Skip aggressive prefetching for large, expensive resources with low actual navigation probability, or on connections where data cost genuinely matters to the user (some mobile data plans) — prefetching everything indiscriminately can waste meaningful bandwidth for marginal benefit.

Getting Started with Prefetching

Next.js automatically prefetches linked pages in the viewport by default:

import Link from "next/link";

<Link href="/products/123">View Product</Link>
// prefetches automatically when the link enters the viewport

Manual prefetching on hover for a more targeted approach:

function ProductLink({ id }: { id: string }) {
  const router = useRouter();
  return (
    <a
      href={`/products/${id}`}
      onMouseEnter={() => router.prefetch(`/products/${id}`)}
    >
      View Product
    </a>
  );
}

Using the Speculation Rules API for browser-native prefetching without JavaScript:

<script type="speculationrules">
{
  "prerender": [{ "where": { "href_matches": "/products/*" } }]
}
</script>

Core Prefetching Strategies Every Developer Should Know

Viewport-based prefetching (the Next.js default) prefetches links as they scroll into view, on the assumption that visible links are reasonably likely to be clicked soon — a good general-purpose default that balances coverage against wasted bandwidth.

Hover/intent-based prefetching triggers on a stronger signal of actual intent — a user hovering over a link is meaningfully more likely to click it than one merely scrolling past it, making this a more targeted (if slightly later-firing) strategy than viewport-based prefetching alone.

Data prefetching (not just route/code prefetching) can front-load API calls for content the user is likely to view next, reducing perceived latency for the actual data fetch as well as the route's code.

Prefetching should be probabilistically justified, not applied uniformly. The value of prefetching a given link is roughly (probability of navigation) × (latency saved) − (bandwidth cost if unused) — links deep in a long list or behind unlikely interactions are worse prefetch candidates than primary navigation links.

Common Prefetching Mistakes and How to Fix Them

Mistake 1: prefetching everything indiscriminately, including large or unlikely-to-be-visited content, wasting bandwidth for low-probability navigations. Fix: be deliberate about what gets prefetched, favoring high-probability navigation targets and lighter-weight resources.

Mistake 2: not accounting for data-sensitive users (mobile data plans, slow connections) when prefetching aggressively. Fix: consider respecting navigator.connection.saveData or connection type to reduce prefetching for users who've signaled data sensitivity.

if (!navigator.connection?.saveData) {
  router.prefetch(href);
}

Mistake 3: prefetching data that changes frequently without considering staleness, showing a user outdated content that was prefetched before an update happened. Fix: pair prefetched data with appropriate revalidation, similar to any cached content strategy.

When Should You Use Aggressive Prefetching Instead of On-Demand Loading?

Use aggressive prefetching (viewport-based, broad coverage) for primary navigation flows where fast perceived performance meaningfully matters to the product experience and bandwidth cost is acceptable for your user base. Use more conservative, intent-based prefetching (hover-triggered, narrower scope) when bandwidth efficiency matters more, or your user base includes meaningful data-sensitive traffic.

Prefetching Strategies in Production

Monitor the ratio of prefetched-but-unused content against your actual bandwidth budget — a prefetching strategy that's too aggressive shows up as wasted bandwidth without a corresponding navigation-speed benefit for most of what's prefetched. Also respect user and browser signals around data sensitivity (saveData, connection type) where your platform exposes them, rather than prefetching uniformly regardless of context.

If your framework's default prefetching behavior (like Next.js's viewport-based Link prefetching) is already active, that's usually a reasonable default — the main additional lever worth considering is more targeted hover-based prefetching for your highest-value navigation paths.

Related posts

Written by Suhail Roushan — Full-stack developer. More posts on AI, Next.js, and building products at suhailroushan.com/blog.

Get in touch