WordPress Caching – OPcache, Redis, Page Cache, CDN, and Speculative Loading
Published: May 20, 2026 · Author: Marcin Szewczyk-Wilgan
Caching is the most impactful category of WordPress performance optimization. A WordPress request that takes 500ms uncached can serve from cache in under 5ms – a 100× improvement. But “WordPress caching” is not one thing: it is a stack of distinct layers, each targeting a different bottleneck. Installing a caching plugin is only one layer of five. This guide covers all of them: OPcache, Redis object cache, full-page cache, CDN, browser cache, and WordPress 6.8's Speculative Loading – what each one does, when to use it, and how the layers work together.
The WordPress Cache Stack
A WordPress request passes through multiple potential cache layers. Each layer hits a different bottleneck.
opcache.memory_consumption and opcache.max_accelerated_files matters significantly for WordPress-scale codebases.Cache-Control and Expires headers on all static assets. WordPress does not set these by default – they must be configured at the web server level.OPcache – The Foundation
OPcache is the most impactful single optimization for WordPress server performance and requires no WordPress-level changes to benefit from.
phpinfo() or Site Health).opcache.memory_consumption = 256 (MB for bytecode storage; default 128 is too low for WordPress + plugins), opcache.max_accelerated_files = 20000 (WordPress installations with many plugins can have 8,000–15,000 PHP files), opcache.interned_strings_buffer = 16 (MB for interned strings – reduces memory for repeated string literals).opcache.validate_timestamps = 1 and opcache.revalidate_freq = 0 so changes take effect immediately. In production: opcache.validate_timestamps = 0 to disable file change checks entirely (reload PHP-FPM after deployments). This eliminates the stat() syscall overhead for every cached file on every request.Redis Object Cache
WordPress has a built-in object cache API, but by default it only caches values for the duration of a single request. A persistent object cache backed by Redis makes the cache survive across requests.
Database queries and computed values
WordPress's WP_Object_Cache stores: query results from WP_Query, term and taxonomy data, user metadata, option autoloads, and anything plugins store via wp_cache_set(). With Redis, these survive across requests so the second visitor to a page generates far fewer database queries than the first.
Redis server and drop-in plugin
Install Redis on the server (or use a managed Redis service). Install the Redis Object Cache plugin by Till Krüss (the most reliable and widely used implementation). The plugin copies a drop-in file to wp-content/object-cache.php which WordPress loads automatically. No other WordPress changes are needed.
High-traffic and multi-user sites
Redis object cache delivers the most benefit when many different visitors request the same pages (cold cache serves them from Redis, not the database) and when the database is a bottleneck. For a blog with under 100 visits/day, the benefit is minimal. For a WooCommerce store or news site with hundreds of concurrent visitors, it can halve database query count.
Plugin transient storage
Many WordPress plugins use the transient API (wp_set_transient / wp_get_transient) to cache external API responses and computed results. With a persistent object cache, transients are stored in Redis instead of the database, eliminating wp_options table queries for frequently accessed transients. This alone can reduce database load significantly on plugin-heavy sites.
Full-Page Cache
Full-page cache stores complete rendered HTML and serves it to anonymous visitors without executing PHP. This is the most dramatic performance improvement for most WordPress sites.
CDN Integration
A CDN accelerates two distinct things: static asset delivery and (optionally) full HTML pages. Even a basic CDN for static assets significantly improves performance for visitors outside your server's geographic region.
Browser Cache
Browser cache keeps assets on the visitor's device after the first download. Subsequent page loads use local copies without making network requests. Without correct Cache-Control headers, browsers re-download unchanged assets on every page visit.
Cache-Control: public, max-age=31536000, immutable. For WordPress media (uploaded images that change infrequently): Cache-Control: public, max-age=604800 (7 days). For HTML pages: Cache-Control: no-cache (must revalidate each visit).?ver=6.5.3) to CSS and JS URLs. This allows long-lived browser cache headers: when an asset changes, the URL changes and the browser fetches the new version. Never set long cache lifetimes on assets without cache-busting mechanisms.location ~* \.(css|js|woff2|png|jpg|svg|ico)$ { expires 365d; add_header Cache-Control "public, immutable"; }. Set in the Nginx server block alongside the WordPress configuration. Most caching plugins also set these headers, but web server-level headers are faster and more reliable.Speculative Loading – WordPress 6.8
WordPress 6.8 (April 2025) introduced the Speculation Rules API integration, branded as Speculative Loading. This is a different mechanism from caching – it prefetches or prerenders pages the user is likely to visit next, making navigation feel instant.
Browser-level prefetch and prerender
WordPress 6.8 outputs a <script type="speculationrules"> element that tells the browser to prefetch (download) or prerender (fully render in a background tab) pages that match specified URL patterns. When the user clicks a matching link, the page is already loaded – navigation appears instantaneous.
Different cost/benefit tradeoffs
Prefetch downloads and parses HTML but does not execute JavaScript or render. Faster to use when clicked, lower resource cost if not clicked. Prerender fully renders the page in a hidden browser context. Navigation is instant, but the cost of a wrong prediction is a full wasted page load. WordPress 6.8 defaults to prefetch; prerender is opt-in.
Automatic and configurable
WordPress 6.8 adds speculative loading rules automatically for internal links, excluding admin, login, checkout, and cart URLs. The wp_speculation_rules filter allows customization. For WooCommerce, verify that the default exclusions cover all dynamic/personalized pages before relying on prerendering.
Pageview inflation
Prerendered pages fire analytics events before the user actually navigates there. This can inflate pageview counts in Google Analytics 4. GA4's enhanced me