Caching Foundation
WordPress caching eliminates redundant PHP execution and database queries by storing rendered output at multiple layers — from the server edge to the user's browser. Most sites see their biggest TTFB and LCP gains by getting page cache and CDN cache correct before chasing deeper PHP or database optimizations.
A proper cache strategy involves layering Edge (CDN), Page (Server), and Object (Database) caches to serve content as quickly as possible while ensuring dynamic actions like checkout and admin functions remain uncached.
Cache Stack at a Glance
| Layer | Purpose | Hits | Misses |
|---|---|---|---|
| Browser cache | Reuse assets already on the user's device. | Repeat visits; static files. | First visit; HTML. |
| CDN edge cache (APO/Tiered) | Serve HTML/assets from a nearby POP. | Public pages; static assets. | First-ever region hits; bypassed cookies. |
| Server page cache (LSCache) | Serve HTML from the web server without PHP. | Public pages; guest users. | Personalized, cart/checkout, logged-in pages. |
| Object cache (Redis) | Speed DB-dependent queries when HTML isn't cached. | Logged-in/admin/checkout; miss after purge. | None (if disabled). |
Action Explanation & Estimated Impact
Ranges are from real-world WordPress sites on decent VPS + Cloudflare. Your mileage varies by theme/plugins, geography, and traffic.
| Action | Why it Matters | Typical Impact |
|---|---|---|
| Enable Server Page Cache (LSCache) | Serves prebuilt HTML directly from server store; skips PHP/DB. | TTFB 0.2–0.6s, LCP 0.4–1.0s, PSI +5–15 |
| Enable Cloudflare APO + Tiered Cache | HTML and assets at the edge; fewer origin trips; Tiered improves hit-rate globally. | TTFB 0.3–0.9s global, LCP 0.3–0.8s, PSI +8–20 |
| Set Browser Cache for static assets (1y immutable) | Repeat visits reuse cached JS/CSS/fonts/images instantly. | Repeat-visit LCP 0.3–0.7s, PSI +5–10 |
| Turn on Redis Object Cache (persistent) | Speeds DB reads/writes for uncached pages (logged-in, cart, search). | Uncached TTFB 0.15–0.4s, INP steadier, PSI +3–8 on dynamic pages |
| Brotli @ CDN + HTTP/2/3 | Smaller transfers and better multiplexing; quicker first paint. | FCP/LCP 0.1–0.3s |
| Guest Mode/Guest Optimization (LSCache) | Ensures first-time visitors get optimized, cacheable HTML even before session starts. | TTFB 0.2–0.4s, LCP 0.2–0.5s, PSI +4–8 |
| ESI blocks for cart/minicart | Cache whole page; hole-punch tiny dynamic fragments. | LCP 0.2–0.5s on Woo product/listing |
| Smart Purge + Warmup | Keeps hit-rate high post-publish; avoids cold cache. | Sustained TTFB/LCP stability, PSI +3–6 consistency |
| Stale-While-Revalidate @ CDN | Serves slightly stale HTML instantly while refreshing in background. | Perceived TTFB near-zero on edge hits |
Static vs Dynamic Strategy
- Static (Blog/Docs/Marketing)
- Dynamic (Woo/LMS/Membership)
Aggressive ON, long TTL for Server Page Cache. ON (APO), long TTL for CDN HTML Cache.
- Highest scores; minimal exceptions.
- Object cache is optional.
- ESI is not needed.
ON with careful bypass rules for Server Page Cache. ON with careful bypass for CDN HTML Cache. ON (Redis) for Object cache. ON for cart/minicart for ESI.
- Cache except
/cart/,/checkout/,/my-account/; vary on auth cookies.
Safe Baseline (LSCache + Cloudflare) with Explanations
| Area | Setting | Why |
|---|---|---|
| LSCache Cache | Cache = ON, Cache Mobile = ON (separate) | Delivers HTML from server store; separate mobile to avoid DOM/CSS drift. |
| LSCache TTL | HTML 17 days, Front page 1 day | Long TTL maximizes hit-rate; purge keeps content fresh. |
| LSCache Do Not Cache | /cart/, /checkout/, /my-account/, ?add-to-cart= | Prevents caching personalized/transactional routes. |
| LSCache ESI | ESI = ON, ESI for cart/minicart | Hole-punch tiny dynamic blocks; keep page cacheable. |
| LSCache Purge | Auto Purge on post/page update; selective purges | Keeps only affected pages fresh; avoids full cold cache. |
| Cloudflare APO | ON + Tiered Cache + Brotli + Early Hints | Edge HTML+assets, better global hit-rates, smaller transfers, faster start. |
| Cloudflare Cache Rules | Bypass for /wp-admin*, cookies like wordpress_logged_in_ | Prevent serving cached HTML to logged-in/admin. |
| Browser Cache (headers) | Static assets: cache-control: max-age=31536000, immutable | Ensures instant loads on repeat visits. |
Expected impact (combined baseline): TTFB 0.5–1.3s, LCP 0.6–1.6s, PageSpeed +15–35 (desktop often >95 for static sites).
Verifying with CLI (commands + expected output)
Run from your workstation or server shell.
Check CDN/Server cache headers
curl -I https://example.com/
Expected output (key lines):
HTTP/2 200
x-litespeed-cache: hit
cf-cache-status: HIT
cache-control: max-age=0, must-revalidate, no-cache, no-store
Interpretation: HTML served from LSCache (hit) and Cloudflare (HIT). HTML often uses short/zero max-age; static assets differ.
Check a static asset
curl -I https://example.com/wp-content/uploads/2025/hero.webp
Expected output:
HTTP/2 200
cache-control: max-age=31536000, immutable
cf-cache-status: HIT
content-encoding: br
Interpretation: 1-year browser cache, immutable, edge hit, Brotli on.
Confirm no-cache route
curl -I https://example.com/checkout/
Expected output:
HTTP/2 200
x-litespeed-cache: miss, no-cache
cf-cache-status: BYPASS
Interpretation: Checkout bypasses caches as intended.
Purge & Warmup Patterns (with benefits)
| Pattern | How | Benefit | Impact |
|---|---|---|---|
| Selective Purge | Purge updated post + homepage, categories, tags | Keeps TTL long elsewhere | Maintains high hit-rate |
| Scheduled Warmup | Use crawler to prefetch top pages after purge | Fewer cold misses after deploy | TTFB/LCP steady after changes |
| Stale-While-Revalidate | CDN serves stale briefly while refreshing | Zero-downtime feel on updates | TTFB feels ~0s on edge hits |
Common Pitfalls & Fixes
| Symptom | Likely Cause | Fix |
|---|---|---|
| Users see old content | Over-long TTL + no purge | Enable auto-purge on update; selective manual purge. |
| Wrong version to logged-in users | Edge caching HTML without cookie bypass | Add cookie-aware bypass rules (WordPress auth cookies). |
| Cart/checkout broken | Cached dynamic routes | Exclude /cart/, /checkout/, ESI cart. |
| Cache fragmentation (low hit-rate) | Vary by user-agent/device/language too broadly | Minimize varies; only separate where layout truly differs. |
| Double optimization conflicts | LSCache + another plugin both minifying/caching | Let LSCache handle page caching; JS/CSS handled by your chosen layer (e.g., Perfmatters). |
Quick Lab (60-90 minutes)
Lab Instructions
- Baseline: Record TTFB/LCP/PSI before changes (mobile + desktop).
- Enable LSCache with rules above; purge all once.
- Enable Cloudflare APO + Tiered + Brotli; create bypass rule for admin/auth cookies.
- Set Browser Cache for assets (1y immutable).
- Turn on Redis (Object Cache Pro/Redis plugin) and confirm
Object Cache: Enabledin WP. - Warm critical routes (home, blog, category, product, product list).
- Re-test: first view and repeat view from two locations.
- Compare deltas: target TTFB 0.8s, LCP 1.0s (static), and PSI +20.
Checklist (print-ready)
View Checklist
- LSCache page cache ON; mobile cache ON (separate).
- Exclusions:
/cart/,/checkout/,/my-account/,?add-to-cart=. - ESI cart/minicart ON.
- TTLs: HTML 17d; front page 1d.
- Cloudflare APO + Tiered + Brotli + Early Hints ON.
- Cache Rules: bypass admin + auth cookies.
- Browser cache for static assets:
max-age=31536000, immutable. - Redis object cache enabled (persistent).
- Purge on update (selective), crawler warmup configured.
- Verified with
curl -Iand PageSpeed/Lighthouse from two regions.
Cheat Sheet (one page)
View Cheat Sheet
| Task | Setting |
|---|---|
| Server page cache | LSCache ON, TTL 17d, exclude cart/checkout/account |
| Edge HTML | Cloudflare APO ON, Tiered ON, Brotli ON |
| Browser | Static assets max-age=31536000, immutable |
| Object cache | Redis ON (persistent), monitor hit-ratio |
| Dynamic fragments | ESI for cart/minicart |
| Purge | Auto on update; selective manual purges |
| Warmup | Crawler on sitemap/top pages after purge |
| Verify | curl -I headers, Lighthouse, WebPageTest |
| Conflicts | One tool for page cache; one for JS/CSS |