HomeMethod

Knowledge

Web VitalsTechniquesSnippetsAnswersImpactsBottlenecks

Page Cache

Store fully rendered HTML on disk or in memory so repeat requests skip PHP and database entirely.

Overview

Page caching captures the final HTML output of a WordPress request and stores it as a static file or in-memory string. Every subsequent visitor for the same URL receives that pre-built HTML instantly — no PHP execution, no database queries, no theme rendering. It is the single highest-leverage optimisation available for most WordPress sites, capable of reducing server response times from seconds to milliseconds.

Impact grade, A+ to D: how much of the Lighthouse score this technique can move. Unaffected: CLS.

The Problem

WordPress is a dynamic CMS: every page request triggers PHP execution, one or more database queries for content and options, template rendering, and plugin hook chains. On a well-optimised server this might take 200–500 ms. On a shared host, a WooCommerce store, or a site with 30+ active plugins it can routinely exceed 1–2 seconds — before the browser even starts downloading the page. High traffic multiplies this problem, creating a queue of requests all waiting on PHP and the database.

Performance Impact

LCP

High

faster TTFB means the browser discovers and starts loading the LCP image sooner

TBT

faster HTML delivery means scripts finish downloading before the main thread becomes congested, slightly narrowing the blocking window

FCP

High

the browser starts rendering the first content immediately after receiving the fast HTML response

SI

instant HTML from cache means the browser begins fetching and painting all resources significantly sooner

TTFB

High

cached HTML is served in under 10ms versus 200ms–2s for dynamic generation

How it works

  1. 01

    First request generates and stores the HTML

    The first visitor triggers the normal WordPress request cycle — PHP, database, template rendering. The caching layer intercepts the final HTML output and writes it to a file on disk (or stores it in Redis/Memcached). The visitor receives the normal response.

  2. 02

    Subsequent requests are served from cache

    For every following request to the same URL, the caching layer detects the stored file and serves it directly — bypassing wp-load.php, all plugin hooks, and every database query. Server response time drops from hundreds of milliseconds to single-digit milliseconds.

  3. 03

    Cache is invalidated on content change

    When a post is published or updated, when a comment is approved, or when a configured TTL expires, the relevant cached files are deleted. The next request regenerates fresh HTML, which is then cached again.

  4. 04

    Logged-in users and dynamic pages bypass cache

    Page caching should never serve cached HTML to logged-in users (who may see personalised content or the WP admin bar) or to pages with user-specific state like /cart, /checkout, or /my-account.

Code Example

Before
// No caching — every request runs full WordPress bootstrap:n// wp-load.php → wp-settings.php → 30+ plugins → DB queriesn// → template render → HTML outputn// Average TTFB: 800ms – 2000ms
After
<?php
// Minimal file-based page cache (add to a custom plugin)nadd_action('init', 'simple_cache_serve', 0);nnfunction simple_cache_serve() {n    if ( is_user_logged_in() ||n         $_SERVER['REQUEST_METHOD'] !== 'GET' ) return;nn    $cache_file = WP_CONTENT_DIR . '/page-cache/'n                . md5( $_SERVER['REQUEST_URI'] ) . '.html';nn    if ( file_exists( $cache_file ) ) {n        readfile( $cache_file );n        exit; // Served in ~5ms — WordPress never bootstrappedn    }nn    ob_start( function( $buf ) use ( $cache_file ) {n        if ( ! is_404() && http_response_code() === 200 ) {n            file_put_contents( $cache_file, $buf );n        }n        return $buf;n    });n}

Production sites should use an established plugin (WP Rocket, W3 Total Cache, LiteSpeed Cache) that handles cache invalidation, exclusion rules, nonces, and multisite edge cases correctly.

Limitations

  • Shopping carts, account pages, checkout flows, and any page that renders user-specific HTML must be excluded. Serving a cached cart page to a different user is a data leak.
  • Nonces embedded in cached HTML expire — form submissions or AJAX actions on long-cached pages may fail. Good plugins handle this by refreshing nonces via JavaScript.
  • Logged-in users — editors, admins, customers — bypass page cache and still experience dynamic load times.
  • File-based caches on large sites with thousands of pages can consume significant disk space.
  • A server-side plugin cache plus a CDN edge cache plus a server-level reverse proxy (Nginx, Varnish) can each hold different versions of a page. When content changes, all layers must be purged. Design your caching stack to ensure purge signals propagate to every layer.

Common Mistakes

Running two page-caching plugins simultaneously

Only one plugin should own advanced-cache.php. Two active page-cache plugins will conflict, potentially serving corrupted HTML or throwing fatal errors.

Caching checkout, cart, or my-account pages

These pages contain user-specific data. Always add them to the cache exclusion list. Most e-commerce-aware plugins exclude WooCommerce pages by default — verify the exclusion is active.

Setting cache TTL so short that pages regenerate constantly

Very short TTLs (under 30 minutes) on rarely-updated content negate the cache benefit. Use event-driven invalidation (clear on post save) with longer TTLs rather than relying on expiry alone.

Not clearing the cache after theme or plugin updates

A theme update changes CSS class names and HTML structure that may be embedded in cached files. Always purge the full page cache after any significant code change.

Test this techniqueCache AnalysisRun the tool

Need help applying this to your site?

Targeted fixes, not guesswork. We identify which techniques move the needle for your specific WordPress stack.

Start an Engagement
Support our family now