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.

Dobromir Dechev
Dobromir WordPress agency owner

Quick answer

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:

ModeWhat it doesCost
prefetchFetches the server response onlyOne HTTP request
prerenderFetches and renders the page, running its JavaScriptA full hidden page load
autoCore decides — currently resolves to prefetch

Eagerness — how early the browser acts:

EagernessFires whenRequests generated
conservativeThe visitor starts clicking a linkVery few
moderateConsiderably earlier — on hoverNoticeably more
eagerEarlier stillMany
immediateInstantlyDisallowed 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.
  • immediate eagerness 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

  1. List your uncached routes. Pull the exclusion rules out of your caching plugin — that is your exposure list.
  2. Check for state-changing pretty permalinks. Any GET route that does something, without a query string, needs an explicit exclusion.
  3. Exclude affiliate and redirect routes. See the tip above.
  4. Decide per site, not globally. A cached brochure site wants the new default. A store with heavy personalisation may want to pin conservative.
  5. 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.
  6. 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?
Probably nothing. This change is designed for exactly that case: a site where nearly every URL is a cacheable static page, served from a full-page cache or a CDN edge. Speculative requests hit the cache, cost your origin nothing, and navigation feels instant. That is the scenario core is optimising for, and if it describes your site you can let the default land.
Does speculative loading affect logged-in users?
No. Core disables speculative loading entirely for logged-in users, and has since it shipped in 6.8. It is also disabled on sites without pretty permalinks. The reasoning is that logged-out pages are the ones that are typically cacheable, so they are the ones where speculation is efficient rather than wasteful. That single rule removes most of the risk for membership sites and admin-heavy workflows.
Will this break my WooCommerce store's cart?
It should not, because core excludes any URL containing query parameters from speculation by default, and most WooCommerce state-changing URLs carry them. But 'should not' is doing work in that sentence. If your store uses pretty-permalink routes that change state, or you have custom endpoints without query strings, add them to the exclusion list explicitly rather than trusting the default to cover you.
How do I turn it off completely?
Return null from the wp_speculation_rules_configuration filter and speculative loading is disabled for that request. That is the supported off switch, and it is a legitimate choice for complex or transactional sites. It is worth measuring before you reach for it, though — the reason this feature exists is that on cacheable pages the speed gain is real and essentially free.

Was this article helpful?