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.

Layer 1: OPcachePHP bytecode cache. Eliminates PHP compilation overhead for every request. Operates entirely in server RAM. No configuration needed beyond enabling it – but tuning opcache.memory_consumption and opcache.max_accelerated_files matters significantly for WordPress-scale codebases.
Layer 2: Object cache (Redis)WordPress database query results and computed values stored in Redis. Reduces database queries per page load. Most effective for sites with many users, complex queries, or heavy plugin use. Requires a Redis server and a drop-in plugin.
Layer 3: Full-page cacheComplete HTML responses cached for anonymous visitors. Can be implemented at the WordPress level (W3 Total Cache, WP Super Cache, LiteSpeed Cache) or at the web server level (Nginx FastCGI cache). Web server-level cache is faster but harder to invalidate automatically.
Layer 4: CDNStatic assets (images, CSS, JS) and optionally full pages delivered from geographically distributed edge nodes close to visitors. Reduces latency for international visitors and offloads bandwidth from the origin server.
Layer 5: Browser cacheBrowser stores assets locally after first download. Subsequent page loads use local copies. Requires correct 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.

How it worksPHP normally tokenizes, parses, and compiles every script from source on every request. OPcache stores the compiled bytecode in shared memory after the first compilation. Subsequent requests load the compiled version from memory, skipping all parse/compile work. For WordPress with 50+ active plugins, this eliminates thousands of file parses per request.
Performance impactOPcache consistently delivers 50–70% reduction in PHP execution time for WordPress. It is the single most impactful PHP-level optimization available. On shared hosting without root access, ensure your host has OPcache enabled (check with phpinfo() or Site Health).
Critical settingsopcache.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).
Development vs productionIn development: 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.

What it caches

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.

Setup

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.

When it matters most

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.

Transients

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.

Plugin-level cacheWP Super Cache, W3 Total Cache, WP Rocket, and LiteSpeed Cache are the most popular plugin-level page cache solutions. They generate static HTML files (or serve from memory) and bypass WordPress's PHP stack for cached pages. Configuration requires careful setup of cache exclusions for logged-in users, dynamic pages, and WooCommerce checkout flows.
Server-level cacheNginx FastCGI cache and Varnish Cache operate at the web server level, before PHP executes. They are faster than plugin-level cache because the request never reaches PHP at all. The tradeoff is more complex cache invalidation – WordPress must signal the cache to purge specific URLs on content updates. Nginx Helper plugin integrates this for Nginx FastCGI cache.
LiteSpeed CacheOn LiteSpeed web servers (increasingly common at modern WordPress hosts), LiteSpeed Cache (LSCWP) provides server-level page caching with WordPress integration. It combines the performance of server-level caching with automatic invalidation on content updates – the best of both approaches. If your host runs LiteSpeed, LSCWP is the obvious choice.
Cache exclusionsAlways exclude from full-page cache: wp-admin, wp-login.php, /cart/, /checkout/, /my-account/, any page returning personalized content (membership areas), POST requests, and any request with the wordpress_logged_in or woocommerce_items_in_cart cookie. Serving a cached personalized page to a different user is a data leak, not just a stale content problem.

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.

Static assetsImages, CSS, JavaScript, fonts, and documents can be served from CDN edge nodes close to visitors. Configure a CDN like Cloudflare or BunnyCDN as a pull CDN: it fetches assets from your origin on first request and caches them globally. Visitors in Tokyo get your assets from a Tokyo edge node, not from a server in Europe.
Full-page CDNCloudflare's Page Cache and BunnyCDN's Perma-Cache can cache full WordPress pages at the edge. This provides the lowest possible latency for anonymous visitors anywhere in the world. Requires careful configuration of cache bypass rules (same rules as local full-page cache, but implemented at the CDN level).
Cloudflare PolishCloudflare Polish automatically converts and compresses images to WebP or AVIF at the CDN edge. This provides AVIF/WebP delivery without any server-side processing and works for images that bypass WordPress's own image processing (directly uploaded files, legacy content, etc.).
WordPress CDN pluginsFor offloading static assets to a CDN, plugins like CDN Enabler, WP Rocket's CDN feature, or W3 Total Cache's CDN integration rewrite asset URLs in WordPress output. Cloudflare operates transparently without URL rewriting since it proxies the entire site.

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 headersFor versioned assets (CSS and JS with content hashes in filenames): 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).
Asset versioningWordPress appends version strings (?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.
Nginx configurationlocation ~* \.(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.

How it works

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.

Prerender vs prefetch

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.

WordPress integration

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.

Analytics impact

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