Skip to content
RU
← All articles

Speculation Rules: Prerendering Pages Before the Click

In short. Speculation Rules let a page tell the browser which links are worth fetching — or fully rendering — before anyone clicks them. A prerendered page activates in roughly the time it takes to repaint, which is as close to instant as navigation gets. The cost is real work done for visits that may never happen, and the control over that cost is one field.

What you are actually asking the browser to do

Two operations hide behind one API, and the difference between them is the difference between a modest and a large commitment.

prefetchprerender
What happensThe document is fetched and heldThe page is fully loaded and rendered offscreen
Runs JavaScriptNoYes — the page behaves as if open
SubresourcesNot fetchedFetched
Cost if unusedOne documentA whole page load
Gain on clickRemoves the document round tripNear-instant display

Prefetch is cheap insurance. Prerender is the one that produces the effect people describe as instant, and it is the one that can quietly multiply your traffic if pointed at the wrong links.

Two speculative paths from a link: one fetching a single document, the other loading and rendering a complete page offscreen
Prefetch collects the document. Prerender builds the whole page in advance — and pays for it whether or not the click arrives.

The syntax

Rules go in a script block of their own. They are JSON, not JavaScript, and they need no library.

<script type="speculationrules">
{
  "prerender": [{
    "where": { "href_matches": "/articles/*" },
    "eagerness": "moderate"
  }],
  "prefetch": [{
    "where": { "href_matches": "/*" },
    "eagerness": "conservative"
  }]
}
</script>

Rules can also exclude, which matters more than it first appears:

{
  "prerender": [{
    "where": { "and": [
      { "href_matches": "/*" },
      { "not": { "href_matches": "/logout*" } },
      { "not": { "href_matches": "/cart/*" } },
      { "not": { "selector_matches": ".no-prerender" } }
    ]},
    "eagerness": "moderate"
  }]
}

Exclude anything with a side effect before you enable anything else. A prerendered page runs its JavaScript, so a link that logs the user out, adds to a cart or consumes a one-time token can fire without a click. The rule set is where you prevent that, and there is no second line of defence.

Eagerness decides how much you waste

ValueTriggers onSensible for
immediateAs soon as the rule is parsedOne near-certain destination
eagerVery slight interaction signalSmall, confident candidate sets
moderateHover, or a brief pause on the linkThe usual choice
conservativePointer or touch down — after the intentLarge link sets, expensive pages

The trade is straightforward: earlier speculation is more likely to be ready and more likely to be wasted. moderate exists because hovering is a genuine intent signal on pointer devices, and it is the right default for most content sites.

Touch devices have no hover, so conservative fires at touch-down — still ahead of the navigation, but by much less. A rule tuned on a desktop will behave differently on a phone, which is worth measuring rather than assuming.

What a prerendered page must handle

Because the page really runs, code that assumes it only executes when visible can misbehave. Three categories matter:

  • Analytics. A pageview fired on load counts visits that never happened. Most analytics libraries now defer automatically, but anything custom will not.
  • Anything with a side effect — writing to storage, consuming a token, starting a session, incrementing a counter.
  • Media and timers. Autoplay is suppressed, but a timer started at load is running long before the user arrives.
// Defer until the page is actually shown
if (document.prerendering) {
  document.addEventListener('prerenderingchange', init, { once: true });
} else {
  init();
}

// After activation, this tells you the page was prerendered
const nav = performance.getEntriesByType('navigation')[0];
if (nav.activationStart > 0) { /* it was */ }

The check is two lines and it is the difference between accurate analytics and inflated numbers that nobody can reconcile later.

A page executing offscreen with a side-effect action firing before any click occurs
A prerendered page runs. Anything that acts on load acts before the visitor has decided to come.

Measuring whether it actually helped

Prerendering makes navigation metrics look extraordinary, and some of that is real while some is an artefact of when the clock starts. Read them with that in mind.

// activationStart is the offset between prerender start and activation.
// Subtract it to get the time the user actually experienced.
const nav = performance.getEntriesByType('navigation')[0];
const perceivedLcp = lcpEntry.startTime - nav.activationStart;

Field data handles this correctly and reports the perceived value, which is why a site with prerendering often shows a genuine improvement in real-user metrics without any change to the page itself. What it cannot show you is the cost, and that lives on the server side: requests for pages nobody opened.

# The signature of speculation in your logs: requests with this header
grep -i 'sec-purpose' /var/log/nginx/access.log | head

# nginx — count them separately so they do not distort your traffic figures
log_format spec '$remote_addr $status "$request" purpose=$http_sec_purpose';

Log speculative requests distinctly from real ones. Without that split, prerendering inflates every traffic figure you have — pageviews, bandwidth, upstream load — and the increase looks like growth rather than like work done on speculation.

When not to use it

  • Pages that cost real money to generate. A report, an export or anything that hits a paid API is a poor candidate for speculative execution.
  • Authenticated flows with side effects. Exclude them explicitly rather than relying on the rules being narrow.
  • Sites with very large link sets and no way to narrow candidates — the waste ratio grows with the number of links the rule matches.
  • Origins under capacity pressure. Speculation adds load precisely when interest is high, which is the moment you have the least headroom.

Where those apply, the resource hints in the resource hints guide are the cheaper instrument: preconnect and preload shorten a navigation you already know is coming, without executing a page that might not be wanted.

A confident narrow candidate set beside a broad one, with the wasted portion visibly larger on the broad side
Waste scales with how many links the rule matches. Narrowing candidates is more effective than tuning eagerness.

Making the destination worth prerendering

Speculation buys you the network time and the render time. It cannot buy back a destination that is slow for its own reasons, and a prerendered page that takes three seconds to become useful still takes three seconds — it just starts earlier.

Three properties decide how much the technique is worth on a given page:

Property of the destinationEffect on the gain
Cacheable, static-ish HTMLLargest gain — activation is nearly free
Personalised per visitorSmaller — the page may refetch on activation
Heavy client-side renderingLarge gain, because the render happens in advance
Blocks on a slow APIGain is real but the wait moves rather than disappears
Sets cookies or session state on loadDo not prerender at all

The third row is where prerendering earns the most and is discussed the least. On a page whose cost is client-side work rather than network, the browser performs that work while the visitor is still deciding — which is exactly the time you would otherwise have no use for.

A rollout that does not surprise anyone

  1. Measure the baseline. Navigation timing and origin request volume, before any rule exists.
  2. Ship prefetch only, conservatively scoped. It is cheap and it exercises the mechanism.
  3. Add the logging split so speculative requests are countable before they become numerous.
  4. Audit destinations for load-time side effects and exclude what you find.
  5. Enable prerender on one narrow set — a single section, not the whole site.
  6. Compare real-user metrics and origin load against the baseline, then widen or stop.

Step three before step five is the ordering that matters. Enabling prerender without a way to count it means the first thing you learn about the cost is whatever your hosting bill or your alerting tells you.

How to check your site right now

Use the HTTP header checker to confirm your pages are cacheable and carry sane Cache-Control — speculation interacts with caching, and a page that cannot be stored gets fetched again on activation, which removes most of the benefit. The speed check gives the baseline navigation timing you need before enabling anything, because "it feels faster" is not a measurement.

Since speculation multiplies requests for pages nobody opened, the load it adds is worth watching rather than assuming. Scheduled monitoring records response time continuously, so a rule that quietly tripled origin traffic shows up as a trend rather than as a surprise on an invoice.

A request volume line stepping upward at the point a speculation rule is enabled
Speculation raises request volume from the moment it ships. Recorded before and after, that step is visible; assumed, it is not.

Frequently asked questions

Resource hints describe individual resources you already know are needed. Speculation Rules describe navigations — and prerender goes further than any hint by executing the destination page rather than merely fetching bytes.

Does it work in every browser?

No, and it does not need to. Browsers without support ignore the script block and navigate normally, so it is a progressive enhancement: the benefit appears where it is supported and nothing regresses where it is not.

Will it inflate my analytics?

It will if your tracking fires on load without checking. Gate initialisation on document.prerendering and the prerenderingchange event, and verify with a real prerendered navigation rather than trusting the library's defaults.

How much extra traffic should I expect?

It depends entirely on how many links the rule matches and the eagerness. Measure it: log requests carrying the speculation purpose header separately, and compare against real navigations for a week before widening the rule.

Can a prerendered page log the user out?

Yes, if the rule matches such a link and the page acts on load. This is the failure worth guarding against explicitly, with exclusions in the rule rather than with care in the destination page.

Should I prerender or prefetch?

Prefetch broadly and prerender narrowly. Prefetch costs one document and helps everywhere; prerender costs a page load and should be pointed only at destinations you are confident about.

Checklist

  • Exclude side-effect links before enabling anything.
  • Start with moderate eagerness and narrow the candidate set, not the trigger.
  • Gate initialisation on document.prerendering.
  • Subtract activationStart when reading navigation metrics.
  • Log speculative requests separately from real ones.
  • Measure origin load before and after shipping the rule.
  • Prefetch broadly, prerender narrowly.
  • Keep destinations cacheable, or activation refetches them.
  • Test on a touch device — there is no hover to trigger on.
  • Never point speculation at anything that costs money to generate.

Check your website right now

Check your site's speed →
More articles: Performance
Performance
Gzip vs Brotli: Web Compression Compared
16.03.2026 · 700 views
Performance
CDN Cache Invalidation: Strategies for Fresh Content
16.03.2026 · 680 views
Performance
Resource Hints: Prefetch, Preload, Preconnect, DNS-Prefetch
16.03.2026 · 536 views
Performance
Latency vs Throughput: Network Performance Metrics
16.03.2026 · 529 views