WordPress Full-Page Caching: Strategies and Implementation

Full-page caching stores the complete HTML output of a WordPress page so subsequent requests are served without executing PHP or querying MySQL. It is the most impactful single performance optimisation for most WordPress sites — the difference between 10ms and 500ms page response time.

Problem: A WordPress site serves dynamically generated HTML on every request — PHP, database queries, and template rendering run for every page view even when the content rarely changes, causing high TTFB under moderate traffic.

Solution: Implement full-page caching: serve static HTML files from disk for anonymous visitors using a plugin (WP Super Cache, W3 Total Cache) or Nginx fastcgi_cache. Configure cache bypass rules for logged-in users, POST requests, WooCommerce cart/checkout pages, and query string parameters. Purge the cache selectively on post save with the save_post hook.

The examples below compare the four main full-page caching strategies, implement a minimal file-based cache in a must-use plugin, and show the correct approach for bypassing cache for logged-in users and WooCommerce cart pages.

# Full-page cache strategy comparison:
#
# Strategy          Where cache lives    Miss cost   Config difficulty
# ─────────────────────────────────────────────────────────────────────
# Nginx FastCGI     Nginx layer          Lowest      Medium (nginx.conf)
# Varnish           Proxy layer          Lowest      High (VCL)
# WP Super Cache    PHP / Apache         Low         Low (plugin)
# W3 Total Cache    PHP / CDN            Low         Medium (plugin)
# Object Cache Pro  Redis (page cache)   Medium      Low (plugin)
#
# Recommended for VPS/dedicated: Nginx FastCGI cache (fastest)
# Recommended for shared hosting: WP Super Cache or W3 Total Cache

# ── Nginx FastCGI Cache setup ──
# /etc/nginx/nginx.conf (http block):
# fastcgi_cache_path /var/cache/nginx/wordpress
#     levels=1:2 keys_zone=WORDPRESS:100m inactive=60m max_size=1g;
# fastcgi_cache_key "$scheme$request_method$host$request_uri";

# /etc/nginx/sites-available/helloadmin.com (server block):
# set $skip_cache 0;
# if ($request_method = POST)        { set $skip_cache 1; }
# if ($query_string != "")           { set $skip_cache 1; }
# if ($request_uri ~* "/wp-admin/")  { set $skip_cache 1; }
# if ($http_cookie ~* "wordpress_logged_in") { set $skip_cache 1; }
# if ($http_cookie ~* "woocommerce_items_in_cart") { set $skip_cache 1; }
#
# fastcgi_cache            WORDPRESS;
# fastcgi_cache_valid 200  60m;
# fastcgi_cache_bypass     $skip_cache;
# fastcgi_no_cache         $skip_cache;
# add_header X-Cache       $upstream_cache_status;

Minimal PHP output-buffer page cache as a must-use plugin:

NOTE: Always bypass the page cache for: logged-in users, POST requests, pages with query strings (except whitelisted SEO parameters), WooCommerce cart/checkout/account pages, and pages with personalised content. A cache that serves logged-in content to anonymous users is worse than no cache at all.

Leave Comment

Your email address will not be published. Required fields are marked *