Nginx Server Caching for WordPress: Ditch Slow Plugins
Large Adelaide WordPress blogs often crawl under plugin page caches. This guide shows how to move caching to Nginx, fix stale HTML and login bleed, and know when Fixwebnode should take over remotely.
If your Adelaide WordPress blog is large, plugin-heavy, and still slow after “optimising,” the bottleneck is often the cache layer itself—not your theme. This guide walks site owners and small-business operators through ditching slow PHP page-cache plugins and implementing proper Nginx server-level caching, with diagnostics you can run over SSH and clear steps for when to book remote WordPress support from Fixwebnode.
Plugin caches (WP Super Cache, W3TC page cache, LiteSpeed-style drop-ins on non-LiteSpeed hosts) still boot PHP on many requests, fight each other, and break under high concurrent traffic. Nginx fastcgi_cache serves static HTML before PHP-FPM wakes up. That is the shift this post covers. Fixwebnode provides direct remote WordPress support for this exact work—config, purge rules, and safe cutover—not a freelance marketplace.
Why server-level caching matters for large WordPress blogs
Adelaide publishers running news, long-form, or multi-author sites routinely hit TTFB spikes when every hit still touches MySQL through a plugin cache. Server-level caching reduces origin load, stabilises Core Web Vitals on mobile, and removes a common source of white-screen conflicts after plugin updates. The goal is simple: anonymous GET traffic served from Nginx disk/memory cache; logged-in, cart, and preview traffic bypassed cleanly.
Why is my WordPress still slow after enabling Nginx fastcgi_cache?
Most often the cache never hits: missing fastcgi_cache_valid, cookies forcing bypass, or a plugin still emitting Cache-Control: no-store. Confirm with response headers and Nginx cache status logs before changing more plugins. If HIT rates stay near zero after a correct config, book Fixwebnode for a remote stack review.
| Symptom | Quick check | When to call Fixwebnode |
|---|---|---|
| Always MISS / BYPASS | Inspect X-Cache-Status and Set-Cookie | Bypass logic unclear across WooCommerce or memberships |
| Logged-in users see public HTML | Verify cookie bypass map | Any personalisation or checkout bleed |
| Stale posts after publish | Purge by URL or cache zone | Need automated purge hooks without another heavy plugin |
Common issues when moving off slow cache plugins
These problems show up repeatedly on large WordPress installs once Nginx caching is introduced or half-configured.
- Cache never hits (constant MISS/BYPASS) — TTFB stays high;
X-FastCGI-Cacheor custom status header never shows HIT. - Logged-in or checkout pages served from public cache — editors see the anonymous homepage; shoppers see another user’s fragments.
- Stale content after publish or update — new posts missing from home/category until a manual full purge hours later.
- Plugin residue fighting Nginx — advanced-cache.php drop-ins, conflicting rewrite rules, or double Gzip/Brotli breaking HTML.
- PHP-FPM or disk cache path errors — 502/404 on cached URIs after reload; empty cache directory permissions.
Issue 1 — Nginx reports MISS or BYPASS on every request
Symptom: page source or headers never show a cache HIT; load average barely drops after “enabling” server cache.
Step 1 — Confirm you are on Nginx + PHP-FPM (not Apache mod_php only)
nginx -v
ps aux | egrep 'nginx|php-fpm' | grep -v egrep
curl -sI https://yourdomain.example/ | egrep -i 'server|x-cache|cache-control|set-cookie'
You want Nginx in front and a way to see cache status. If headers are messy, add a status header in the cache block (next steps).
Step 2 — Define a cache path and keys zone
In http {} (often /etc/nginx/nginx.conf):
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=WORDPRESS:100m inactive=60m max_size=2g;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
Create the directory and lock down ownership:
sudo mkdir -p /var/cache/nginx/fastcgi
sudo chown -R www-data:www-data /var/cache/nginx/fastcgi
# On RHEL-family hosts use nginx:nginx instead of www-data
Step 3 — Skip non-cacheable methods and admin paths
map $request_method $skip_cache_method {
default 0;
POST 1;
}
map $request_uri $skip_cache_uri {
default 0;
~*^/wp-admin 1;
~*^/wp-login\.php 1;
~*^/xmlrpc\.php 1;
~*\? 1;
}
Step 4 — Enable cache inside the PHP location
set $skip_cache 0;
if ($skip_cache_method) { set $skip_cache 1; }
if ($skip_cache_uri) { set $skip_cache 1; }
if ($http_cookie ~* "wordpress_logged_in|comment_author|wp-postpass|woocommerce_items_in_cart|wordpress_sec") {
set $skip_cache 1;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-FastCGI-Cache $upstream_cache_status;
}
Adjust the PHP-FPM socket to match your host (ls /run/php/ or /var/run/php-fpm/).
Step 5 — Test and reload
sudo nginx -t && sudo systemctl reload nginx
curl -sI https://yourdomain.example/ | grep -i X-FastCGI-Cache
# First request: MISS; second: HIT
When to call Fixwebnode: HIT never appears, or your host uses a control panel that rewrites vhosts on every save. Remote specialists can pin the include order and stop panel overwrites.
Issue 2 — Logged-in users or carts see cached public pages
Symptom: admin bar missing for editors; “wrong” menu or cart count; privacy risk on membership content.
Step 1 — Inventory cookies WordPress and commerce plugins set
curl -sI -c /tmp/wp_cookies.txt -b /tmp/wp_cookies.txt https://yourdomain.example/wp-login.php
# After a real browser login, DevTools → Application → Cookies
# Note wordpress_logged_in_*, woocommerce_items_in_cart, wp_woocommerce_session_*
Step 2 — Tighten the bypass map
map $http_cookie $skip_cache_cookie {
default 0;
~*wordpress_logged_in 1;
~*woocommerce_items_in_cart 1;
~*wp_woocommerce_session 1;
~*comment_author 1;
~*wp-postpass 1;
}
Combine with your existing $skip_cache flag so any match forces bypass.
Step 3 — Never cache REST, cron, or preview
if ($arg_preview = "true") { set $skip_cache 1; }
if ($request_uri ~* "/wp-json/") { set $skip_cache 1; }
if ($request_uri ~* "/feed/") { set $skip_cache 1; }
Step 4 — Verify with two sessions
# Anonymous
curl -sI https://yourdomain.example/ | grep X-FastCGI-Cache
# Should trend to HIT
# Simulated logged-in cookie (use a real cookie value from your browser)
curl -sI -H "Cookie: wordpress_logged_in_test=1" https://yourdomain.example/ | grep X-FastCGI-Cache
# Must be BYPASS or EXPIRED, never HIT of public HTML
When to call Fixwebnode: multi-site, custom membership cookies, or headless front ends where cookie names are non-standard. Incorrect bypass is a data-leak class issue—do not guess in production.
Issue 3 — Stale HTML after publish, update, or comment
Symptom: homepage and archives show old headlines; single post updates only after waiting out inactive= TTL.
Step 1 — Manual purge of the cache zone (emergency)
sudo find /var/cache/nginx/fastcgi -type f -delete
sudo systemctl reload nginx
curl -sI https://yourdomain.example/ | grep X-FastCGI-Cache
Step 2 — Prefer targeted purge over wiping everything
If you use ngx_cache_purge (module must already be compiled in):
location ~ /purge(/.*) {
allow 127.0.0.1;
allow ::1;
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
curl -sX PURGE http://127.0.0.1/purge/your-post-slug/
Without that module, keep TTLs modest (5–15 minutes for highly editorial homes) and purge the zone on deploy.
Step 3 — Stop plugin page caches from writing advanced-cache.php
ls -la wp-content/advanced-cache.php wp-content/object-cache.php
# Disable page-cache features in old plugins; keep object cache (Redis) if present
grep -n "WP_CACHE" wp-config.php
Set define('WP_CACHE', false); only if nothing else legitimate needs it; remove stale drop-ins after a full backup.
Step 4 — Align WordPress “discourage search engines” and CDN layers
If Cloudflare or another CDN sits in front, either purge both layers on publish or let Nginx be the origin cache with CDN cache rules matching your bypass cookies. Mismatched TTLs are the usual “I purged Nginx but still see old HTML” report.
When to call Fixwebnode: you need publish-time purge hooked to WordPress without installing another bulky cache plugin, or CDN + Nginx double-cache is fighting editorial workflow.
Issue 4 — 502 errors or empty responses after enabling fastcgi_cache
Symptom: intermittent 502 Bad Gateway; error log mentions upstream or cache temp dir.
Step 1 — Read the real error
sudo tail -n 100 /var/log/nginx/error.log
sudo tail -n 100 /var/log/php8.2-fpm.log
# Paths vary: /var/log/php-fpm/www-error.log on some hosts
Step 2 — Fix permissions and temp paths
sudo ls -la /var/cache/nginx/fastcgi
sudo chown -R www-data:www-data /var/cache/nginx/fastcgi
# Ensure fastcgi_temp_path is writable if overridden
grep -R fastcgi_temp /etc/nginx/ -n
Step 3 — Validate upstream socket and pool
sudo systemctl status php8.2-fpm
sudo nginx -t
sudo systemctl restart php8.2-fpm
sudo systemctl reload nginx
Step 4 — Watch status under load
curl -sI https://yourdomain.example/ | grep -E 'HTTP|X-FastCGI-Cache'
# Repeat; confirm no 502 and HIT after warm-up
When to call Fixwebnode: 502s persist after socket and permission fixes, or SELinux/AppArmor denials appear in audit logs on hardened Adelaide VPS images.
Issue 5 — Old cache plugins still slow the admin and break deploys
Symptom: wp-admin sluggish; “cache” plugins re-enable drop-ins after updates; duplicate minification.
Step 1 — Inventory active cache-related plugins
wp plugin list --status=active --fields=name,status,version
# or from wp-content/plugins without WP-CLI:
ls wp-content/plugins | egrep -i 'cache|super|w3tc|litespeed|wp-rocket|comet'
Step 2 — Disable page caching features only
Keep useful pieces (image lazy-load config, separate Redis object cache) if they are healthy. Turn off page cache, database “query cache” gimmicks, and HTML minify that strips nonces.
Step 3 — Clear opcode and restart PHP once
sudo systemctl restart php8.2-fpm
wp cache flush 2>/dev/null || true
Step 4 — Re-test front-end HIT and admin responsiveness
curl -sI https://yourdomain.example/ | grep X-FastCGI-Cache
# Admin should no longer depend on a PHP page cache plugin
When to call Fixwebnode: tangled mu-plugins, licence-locked “all-in-one” optimisers, or a host-specific cache agent you cannot safely remove alone.
When DIY is enough vs when to book Fixwebnode
DIY is enough when you have SSH, a standard Nginx + PHP-FPM vhost you control, no complex membership/checkout cookie matrix, and you can demonstrate anonymous HIT plus logged-in BYPASS with curl. Follow the numbered steps above, keep a backup of each Nginx file before edits, and change one variable at a time.
Book Fixwebnode when any of these apply: panel-managed Nginx that overwrites your includes; WooCommerce or memberships with custom cookies; CDN double-caching; recurring stale home pages after editorial publish; 502s after every cache change; or you simply cannot afford a mistaken public cache of private HTML. Fixwebnode works as a direct remote specialist for WordPress support—configuration, verification headers, and purge design—across our service areas, including remote work for Adelaide-based sites and teams.
Soft timing only: remote sessions are often arranged same-day when booked early, depending on queue and access readiness (SSH key or panel login, staging preference, and a recent backup).
Talk to Fixwebnode about Nginx caching for your WordPress blog
Large blogs should not lean on slow PHP page-cache plugins when Nginx can answer anonymous readers in microseconds. If you want a clean cutover—HIT/BYPASS rules verified, stale-content purges that match how your editors publish, and leftover plugin drop-ins removed—start a conversation with Fixwebnode.
Book remote help via our WordPress support page. Bring your domain, current cache plugins list, and whether WooCommerce or memberships are in play; we will focus on server-level caching done safely, not on generic “speed tips.”