WordPress 7.1 Turns Speculative Loading Up to Moderate: What to Check First
WordPress 7.1 raises the speculative loading default from conservative to moderate on cached sites. What it costs your origin, and how to tune it.
WordPress 6.8 shipped speculative loading with a deliberately timid default: prefetch, conservative eagerness, which only fires once a visitor has started clicking. WordPress 7.1, due August 19, 2026, raises that default to moderate eagerness on sites where core detects a caching layer. Moderate fires far earlier — on hover — which means noticeably more requests hitting your origin for pages nobody ends up visiting. For a well-cached brochure site that is free speed. For WooCommerce stores, membership sites, and anything with uncached routes or per-visitor pricing, it is worth auditing before the release rather than after.
WordPress 6.8 quietly added one of the more effective performance features core has shipped in years, and set it to its most cautious possible setting. WordPress 7.1, out August 19, turns it up.
The change is a single word in a default — conservative becomes moderate — and on most sites it will make navigation feel dramatically faster at no cost. On a meaningful minority it will send a lot more traffic to your origin than you were expecting. Knowing which category each client site falls into takes about ten minutes.
What speculative loading actually does
Speculative loading is WordPress's implementation of the browser Speculation Rules API. The site tells the browser, in a small block of JSON, which links it may fetch or render before the visitor clicks them. When the visitor does click, the page is already there.
Two dimensions control it.
Mode — how much work the browser does ahead of time:
| Mode | What it does | Cost |
|---|---|---|
prefetch | Fetches the server response only | One HTTP request |
prerender | Fetches and renders the page, running its JavaScript | A full hidden page load |
auto | Core decides — currently resolves to prefetch | — |
Eagerness — how early the browser acts:
| Eagerness | Fires when | Requests generated |
|---|---|---|
conservative | The visitor starts clicking a link | Very few |
moderate | Considerably earlier — on hover | Noticeably more |
eager | Earlier still | Many |
immediate | Instantly | Disallowed in core config |
WordPress 6.8 shipped with prefetch + conservative. That combination is close to free: it only starts fetching once a pointer is already going down on a link, so it buys you maybe 100–200ms and almost never fetches a page nobody visits.
What changes in 7.1
The default moves to moderate eagerness — but only where core detects that the site has a caching layer in front of it.
That conditional is the important half of the sentence, and it is also the half I would verify against Release Candidate 1 on August 5 before making plans around it. "Caching detected" is doing a lot of work, and precisely which signals core uses to decide determines whether your stack opts in. If you run page caching at the edge via Cloudflare rather than through a WordPress plugin, whether core notices is worth confirming rather than assuming.
The logic behind gating on caching is sound: speculation is only cheap when the speculated page is served from cache. Moderate eagerness on an uncached site means your PHP workers generate full pages for visitors who hovered over a link and moved on.
Why moderate is a different risk profile
Conservative eagerness is a prediction made at the last possible moment, when the user has essentially already committed. Its hit rate is very high, so wasted requests are rare.
Moderate fires on hover. People hover over a lot of links they never click — scanning a nav menu, reading a list of related posts, moving the pointer across the screen on the way somewhere else. The hit rate drops, and the number of speculative requests per session rises.
If those requests are all served from a full-page cache or a CDN edge, this genuinely does not matter. The cache absorbs them and the visitor gets instant navigation. That is the whole bet, and for a large fraction of WordPress sites it is a good one.
The bet goes wrong in three situations.
Sites with uncached routes
Any URL that bypasses your page cache is now a candidate for being generated on hover. Search results pages, filtered archive URLs, anything personalised, anything your caching plugin excludes by rule. If you have a long exclusion list in your cache configuration, read it as a list of URLs that may now be generated speculatively.
Our caching plugin roundup covers how each of the major plugins handles exclusions, which is the list you want in front of you here.
WooCommerce and anything transactional
Core excludes URLs containing query parameters from speculation by default, which was a deliberate safeguard against "action URLs" that change state via GET. Most WooCommerce add-to-cart and checkout flows carry query strings, so the default covers them.
The gap is custom routes. If you or a previous developer built pretty-permalink endpoints that do something — a one-click action, a tracking redirect, a custom coupon route — those have no query string and no automatic protection. With prerender they would not just be fetched but executed.
Core defaults to prefetch, not prerender, which limits this considerably: a prefetch fetches the response without running client-side code. But a GET request that mutates state does not care whether the browser rendered the result. Audit for those routes.
Our checkout optimisation guide covers the wider set of WooCommerce URL patterns worth treating carefully.
Analytics and ad impressions
This one is easy to miss and directly affects revenue on ad-supported sites.
With prefetch, only the HTML is fetched — no JavaScript runs, so analytics and ad scripts do not fire. That is the safe case, and it is the core default.
With prerender, the page is rendered in a hidden state and its JavaScript does execute. Modern analytics libraries and ad scripts are generally built to handle this via the Page Visibility API, deferring their events until the page is actually activated. But "generally" is not "always", particularly for hand-rolled tracking, older tag setups, and anything that fires an event on DOMContentLoaded without checking document.prerendering.
If you serve display ads, this is worth being careful about: impressions counted on pages the visitor never saw are exactly the kind of thing ad networks treat as invalid traffic. Since core defaults to prefetch, you are fine unless you have deliberately switched to prerender — but if you have, verify your tag behaviour before turning eagerness up.
What core already protects you from
Before you start writing exclusion rules, know what you get for free:
- Logged-in users are excluded entirely. Speculative loading does not run for them at all.
- Sites without pretty permalinks are excluded entirely.
- URLs with query parameters are excluded by default.
immediateeagerness is not permitted in core's configuration, so the most aggressive setting is off the table.
Between the logged-in exclusion and the query-parameter exclusion, most membership sites and most stores are substantially covered already.
How to tune it
Everything is filterable, and the API is small enough to fit in a snippet.
Change the mode and eagerness, or switch it off:
add_filter( 'wp_speculation_rules_configuration', function ( $config ) {
// Return null to disable speculative loading for this request.
if ( is_cart() || is_checkout() || is_account_page() ) {
return null;
}
// Or pin it back to the 6.8 behaviour site-wide.
return array(
'mode' => 'prefetch',
'eagerness' => 'conservative',
);
} );
Exclude specific paths, optionally per mode:
add_filter(
'wp_speculation_rules_href_exclude_paths',
function ( $paths, $mode ) {
$paths[] = '/go/*'; // affiliate redirects
$paths[] = '/download/*'; // one-shot download routes
if ( 'prerender' === $mode ) {
$paths[] = '/members/*'; // don't execute personalised pages
}
return $paths;
},
10,
2
);
Exclude a single link without touching PHP — add the no-prefetch or no-prerender class to a block via the Advanced → Additional CSS class(es) field in the editor. Useful for one-off links inside content where a filter would be overkill.
Add entirely custom rules via the wp_load_speculation_rules action, which receives a WP_Speculation_Rules instance if you need finer control than the exclusion list allows.
A pre-release checklist
- List your uncached routes. Pull the exclusion rules out of your caching plugin — that is your exposure list.
- Check for state-changing pretty permalinks. Any GET route that does something, without a query string, needs an explicit exclusion.
- Exclude affiliate and redirect routes. See the tip above.
- Decide per site, not globally. A cached brochure site wants the new default. A store with heavy personalisation may want to pin conservative.
- Verify what "caching detected" means for your stack once RC1 lands on August 5, particularly if your caching is at the CDN edge rather than in a plugin.
- Watch origin request volume for a week after rollout. A jump in requests with flat pageviews is the signature of speculation you did not want.
Should you just turn it off?
No — not by default, anyway.
It is worth being clear that this feature is good, and the direction core is taking it is defensible. Instant navigation is one of the few remaining wins available once you have already done the obvious work on images, caching, and server response time. If your site is genuinely cacheable, moderate eagerness will make it feel faster than any amount of additional image optimisation will.
The reason to spend ten minutes on it is that speculative loading moves work from "when the user asks" to "when the user might ask", and that trade only pays off when the work is cheap. Confirm it is cheap on each site, exclude the handful of routes where it isn't, and let it run.
This shipped in the final 7.1 build — see what else landed in "Mary Lou" before you schedule the update.
If the answer turns out to be that a lot of your routes are uncached, that is worth knowing for reasons well beyond this release — see our Core Web Vitals fix checklist and, if TTFB on uncached routes is the underlying problem, the hosting speed test.
Frequently Asked Questions
Do I need to do anything if my site is a simple cached brochure site?
Does speculative loading affect logged-in users?
Will this break my WooCommerce store's cart?
How do I turn it off completely?
// new_articles
Get notified when new guides drop
Practical WordPress guides from a working agency owner. No filler. Unsubscribe any time.
Was this article helpful?
Thanks for the feedback!