alion tech studio
  • services
  • faq
  • insights
  • about
  • contact
← back to insights
  1. home
  2. insights
  3. speculation rules api
jul 5, 2026 • 10 min read • web performance

instant navigations with the speculation rules api

By Alex I

Most performance work optimises the page the user is already looking at. This article is about the other page — the one they are about to look at. As of this week, the site you are reading speculatively prefetches internal pages the moment you show intent to visit them, so that by the time you click, the HTML is usually already on your device. The whole implementation is eleven lines of JSON. This is the write-up of what we deployed, how the API works, and the sharp edges we deliberately steered around.

the gap you can steal from

There is a consistent, measurable delay between a user signalling intent and committing to it: hovering a link before clicking, or touching a link before lifting the finger. Across published studies this hover-to-click gap sits in the range of a few hundred milliseconds — and on this site, a whole article page is roughly 25 KB of HTML. Those two numbers are the entire business case: the network time to fetch the next document fits comfortably inside the intent gap, so if the browser starts the fetch on hover instead of on click, the navigation itself feels instantaneous. None of this is new as an idea — libraries like quicklink and instant.page have done it with JavaScript for years, and frameworks ship router-level prefetching. What is new is that the browser now does it natively, declaratively, and smarter than a script can.

what the speculation rules api is

The Speculation Rules API replaces the older, weaker <link rel="prefetch"> with a JSON block that tells the browser which future navigations to prepare and how aggressively. It supports two levels of preparation:

  • Prefetch downloads the target document's HTML ahead of time and holds it in a memory cache. On navigation, the response is already local — you save the network round-trip, but the browser still parses, fetches subresources, and renders normally.
  • Prerender goes all the way: it fetches the document and renders it in an invisible background page — subresources loaded, scripts executed, layout done. Activating it on click is close to instantaneous, like switching to an already-open tab.

Both are declared in a <script type="speculationrules"> block, and unlike the old prefetch hint — which was a low-priority suggestion browsers frequently ignored — speculation rules are a first-class mechanism with document-level semantics, URL pattern matching, and built-in safety behaviour.

the exact rules this site now ships

Here is the complete block we added to every page, verbatim:

<script type="speculationrules">
{
  "prefetch": [{
    "where": {
      "and": [
        { "href_matches": "/*" },
        { "not": { "href_matches": "/contact" } }
      ]
    },
    "eagerness": "moderate"
  }]
}
</script>

Reading it line by line: the where clause is a document rule — instead of listing URLs, it tells the browser to consider every same-origin link on the page (href_matches: "/*") except the contact page, which we exclude simply because a form page benefits least and we would rather not speculate anything with interactive state. The eagerness field is where the intent detection lives, and it is the most interesting knob in the API.

The four eagerness levels. "moderate" is the sweet spot for content sites: near-zero waste, and the intent gap still hides the fetch.
eagernesswhen the browser actswaste riskbest for
immediateas soon as the rule is parsedhigh — fetches whether or not the user ever clicksthe one page almost everyone visits next
eageron the earliest hint, e.g. the pointer merely approachingmedium-highshort link lists with high click-through
moderateon hover (~200 ms) or touchstartlow — the user is already signalling intentcontent sites, blogs, docs — and this site
conservativeon pointerdown / touchstart, just before the click completesminimalmetered-traffic-sensitive or huge pages

With moderate, nothing at all happens while you merely read. Hover any internal link for a fifth of a second — or touch it on a phone — and the browser quietly fetches that page. Click, and the document comes out of the speculation cache instead of the network. If you never click, you have cost us one ~25 KB request; the browser also caps concurrent speculations and evicts stale ones, so the failure mode is bounded by design.

why we chose prefetch over prerender

Prerender demos better — activation is genuinely instant — but it executes the page, and executing a page has side effects. A prerendered page that runs analytics records a visit that may never happen. A prerendered page that renders ads can register impressions no human saw, which is a policy problem with ad networks, not just a data-quality one. The platform provides tools to handle this properly: a prerendered page can check document.prerendering and defer side-effectful work until the prerenderingchange event fires on activation, and major analytics vendors now do this. But every third-party script on the page has to get it right, and on a site that serves ads we prefer the option with no failure mode: prefetch moves bytes, executes nothing, and triggers neither analytics nor ad code until a real navigation happens.

If your pages are self-contained and script-light — internal tools, documentation — prerendering the most likely next page is a legitimately spectacular upgrade, and the rule is one word different: "prerender" instead of "prefetch". Start with the same moderate eagerness and measure.

seeing it work

Chrome's DevTools has a dedicated view for this: Application → Background services → Speculative loads shows each rule the page declared, which URLs have been speculated, and whether a navigation used the speculation. The Network panel tells the same story — hover a link on this site with DevTools open and you will see the document request fire with a Sec-Purpose: prefetch header before any click, then the navigation itself served from the prefetch cache. That header also matters server-side: it is how your logs distinguish speculative fetches from real page views, and how a server could opt out of speculation for specific routes if it needed to.

One practical note from deploying this: prefetched documents respect normal HTTP caching semantics. Our HTML is served with max-age=0, must-revalidate (the reasoning is in our caching guide), and prefetch handles that correctly — the speculation cache is a separate, short-lived holding area, so a stale prefetch does not outlive the navigation it was made for.

when you should not speculate

Declarative does not mean thoughtless. Some links should never appear in a speculation rule, and the where clause exists precisely to carve them out:

  • Anything with side effects on GET — logout links are the classic self-inflicted wound: an eager speculation logs the user out while they hover the navigation menu. (Logout should be a POST anyway; speculation is one more reason.)
  • Authenticated or highly personalised pages, where a prefetched response may not match the state the user has by the time they navigate.
  • Very large pages or files — speculating a link to a 40 MB PDF turns a micro-optimisation into a bandwidth bill.
  • Cross-origin links have stricter rules by default (prefetch works but without credentials unless opted in), and are usually not worth the complexity.

The browser also applies its own guardrails on top of yours: it will not speculate when the user has Data Saver enabled, on battery-saver in some configurations, or past its internal limits on concurrent speculations. You declare intent; the browser retains judgement.

browser support and the cost of being wrong

Speculation rules are a Chromium feature — Chrome and Edge support them fully; Safari and Firefox currently do not. That sounds like a problem until you notice the failure mode: a browser that does not recognise <script type="speculationrules"> ignores it completely. No error, no polyfill needed, no behavioural difference except the absence of a speed-up. It is the textbook shape of a progressive enhancement, which is why we were comfortable shipping it to every page the same afternoon we wrote it. Chromium is a large enough share of our traffic that most visitors get faster navigations, and nobody gets a slower or broken one.

the takeaway

The Speculation Rules API is the rare optimisation with an almost embarrassing effort-to-payoff ratio: eleven declarative lines, no build step, no JavaScript library, bounded waste, and graceful degradation everywhere it is unsupported. The craft is not in the code but in the choices — prefetch versus prerender based on what executing your pages costs, an eagerness level matched to how users actually move through your site, and a where clause that excludes the links that should never be guessed at. We chose the conservative end of each of those dials for this site, and the next click you make here should be the proof.

AX

Alex I

Software engineer and founder of alion tech studio. Writes and consults on web performance, security, mobile apps, backend systems, cloud infrastructure, and fullstack architecture.

related reading

may 28, 2026 • 11 min read • web performance

a practical field guide to core web vitals in 2026

read article →
jun 26, 2026 • 14 min read • web performance

http caching headers: Cache-Control, ETags, and browser caching done right

read article →
alion tech studio

an independent software engineering studio. we write about performance, security, and building for the web, and consult on the same.

navigation

  • services
  • faq
  • insights
  • about
  • contact

legal

  • privacy policy
  • terms of service

© 2026 alion tech studio. all rights reserved.