Prefetch

Method

Downloading a resource before the user asks for it, so the wait disappears at the moment they actually click.

Why it exists

Time spent waiting for a screen is generally felt in full. Start fetching code and data only after the link is clicked and that stretch becomes time the user can do nothing with.

Theo measured how long opening one document from the list took and got 700 milliseconds. Five hundred of those went to downloading the editor code bundle. Meanwhile, during the three seconds a user spends reading the list and deciding which document to open, the network sat idle.

What stood out was that the delay came from when the fetch started rather than from the weight of what was fetched. Spend those same 500 milliseconds while the user is still deciding and only 200 remain after the click.

Prefetching moves that starting point earlier. Something not needed by the current screen but likely to be needed next gets pulled down during the idle stretch. Guess right and the wait vanishes; guess wrong and what arrived gets thrown away. So the technique buys speed by wagering bandwidth, and whether the wager pays depends entirely on how well the next action can be predicted.

How to run it

What to fetch early gets decided from records, not from intuition. Start by counting what people did next after viewing the list screen.

  1. Write the next action as a probability. If 80 percent of people on the list open a document and 3 percent go to settings, the editor is what to fetch.
  2. Choose the targets. Candidates are the next screen's code bundle, the data that screen will request, font files, and images that will appear above the fold. Large and slow-changing is where the value is, because a big file saves more time and a stable one stays useful long enough to be worth the gamble.
  3. Decide when to start. Right after the current screen finishes rendering, the moment a pointer enters a link, or once the list is scrolled to the end. Starting on hover raises the hit rate but shrinks what you can win to roughly 300 milliseconds.
  4. Request at lowered priority. Ask at the same priority as what the current screen needs and the current screen gets slower. Flag the request so the browser knows it can wait.
  5. Attach conditions. Skip it when the user has a data-saving mode on or the connection is detected as slow. Otherwise you are spending somebody else's data allowance on files they never open, which is the one failure mode users can actually notice.
  6. Measure the hit rate — the share of prefetched resources actually used. Without it there is no way to tell whether the technique is helping or just costing.

Step 6 is the one most often skipped. Leave the hit rate unmeasured and a state where bandwidth rose while the experience didn't can persist for months. Below half means either the target or the timing was chosen wrong, and the fix is usually the timing rather than the target.

When it fits and when it doesn't

It fits flows where the next action narrows sharply: a list leading into a detail view, a signup with fixed steps, a reading screen with a next page. On the resource side, font files and code bundles are good targets — both large, and both stable once fetched. Paired with bundles split by code splitting, only the needed piece gets pulled early. Code splitting divides code into pieces so each arrives only when it's needed.

Where it doesn't fit is equally clear.

  1. Screens with wide choice. On a dashboard, where people go next scatters, and the hit rate falls under 20 percent. Fetch five and use one and four fetches worth of bandwidth is wasted, every time the screen loads, for every user.
  2. Data that changes often. It begins going stale the moment it arrives. Show a list fetched three minutes ago and the user clicks a document that no longer exists.
  3. Large images and video. Big and low hit rate is the combination with the worst loss.
  4. Mobile data. The cost comes out of the user's allowance and battery, neither of which shows up in any dashboard you own.

Server-side cost belongs in the picture too. A prefetch request still reaches the server, so requests nobody will use still get served. Sitting behind a CDN softens that; a CDN is the distribution network that serves resources from a point close to the user.

How it sounds at work

"Prefetch the editor bundle from the list and opening drops to 200 milliseconds."

Fetch early what was being fetched after the click, and the wait goes away.

"I switched it to start on hover. Fetching everything upfront wasted too much."

The start moved later to raise the hit rate.

"Prefetch hit rate is 30 percent. This is just adding bandwidth."

Most of what gets fetched early is being discarded.

Pagedeck prefetches only the editor code bundle from the document list. Theo's first version also pulled the contents of the ten documents visible in the list, and the hit rate came back at 12 percent — ten fetched, one used.

So contents narrowed to the single document under the pointer. The code bundle is the same whichever document opens, so it starts right after the screen renders, while contents start on hover. The two timings differ because the two hit rates do. Noa asked for both to switch off under data-saving mode, so that condition went on as well. Opening a document now measures around 200 milliseconds against the original 700.

What people get wrong

The most common reading is that fetching more early makes everything faster. Fetching ahead is a gain, so more of it looks like more gain. But network and processing capacity are finite, and while unused resources download, the ones the current screen needs get pushed back. Prefetch twenty items from a list screen and the list itself renders late, so the user meets the slower list before ever seeing the faster detail view.

Expecting the first screen to get faster is also frequent. It's a performance technique, so it seems like everything should speed up, but this is a story about the second screen onward. On a first visit there is no basis for fetching anything early, and prefetch requests can actually delay the first screen's LCP. LCP is the time until the largest piece of content is painted. Making a first screen fast is handled by reducing what has to arrive at all, which is a different set of techniques with a different set of trade-offs.

Easily confused with

TermWhen the resource is fetchedHow it differs
CachingStores what was already fetched and reuses itReuse of something already received. Prefetch pulls something never received yet, so it helps even on a first visit
Lazy loadingDefers until the moment of needThe opposite direction. Things that may never be seen, like images far down the page, get deferred; things likely to be seen next get pulled forward

Where to go next

  • Web performance

    see which branch of the work this technique belongs to

  • Caching

    the partner it's most often used with

Last updated 2026-09-16