WordPress cache warming: preload your page cache and your CDN
An uncached WordPress page is expensive: PHP boots, the theme renders, plugins run their hooks, and MySQL answers a few dozen queries. On typical shared hosting that's 500 ms to several seconds of server time — for every single uncached request. That's why every serious WordPress setup caches. And why the pages that aren't in cache when a visitor arrives are the ones that hurt.
The catch most guides skip: WordPress sites have two separate caches that go cold independently — and the popular "preload" features only warm one of them.
The two caches (and who warms what)
| Layer | Where it lives | Warmed by |
|---|---|---|
| Page cache | Your server (WP Rocket, LiteSpeed, W3TC, FlyingPress, host-level cache) | Plugin preload / crawler |
| CDN edge cache | 300+ data centers worldwide (Cloudflare, bunny.net, …) | Nothing, by default |
The page cache stores rendered HTML on your server so PHP and MySQL are skipped. The CDN edge cache stores that HTML in data centers close to your visitors, so the request never reaches your server at all. A visitor served from the edge gets the page in tens of milliseconds; a visitor who misses both caches waits for the full PHP render plus the round trip across the globe.
What plugin preload actually does
Most caching plugins ship a preload feature, and they're genuinely useful:
- WP Rocket reads your sitemap and requests every URL after the cache lifespan expires or after you clear the cache, rebuilding the page cache in the background.
- LiteSpeed Cache has a server-side crawler that walks the sitemap on a schedule — including separate passes for mobile and per-cookie cache variations.
- FlyingPress and W3 Total Cache do sitemap-based preloading in the same spirit.
All of these run on or next to your server. They warm the origin page cache — and that's all. The request that fills the page cache in your hosting data center does nothing for the Cloudflare colo in Sydney, São Paulo or Singapore. If your CDN caches HTML, each of its hundreds of edge locations still starts cold and stays cold until a real visitor from that region takes the slow first hit.
Rule of thumb: plugin preload fixes the server-side cold cache. It cannot fix the edge-side cold cache, because warming an edge cache requires requests that physically enter the CDN network at each location. One server can't do that — this is the same geography problem we covered for Cloudflare.
Step 1: get the page cache right
- Pick one page cache. Two caching plugins fight each other. If your host caches at the server level (most managed WordPress hosts do), you often don't need a plugin page cache at all.
- Enable its preload/crawler and point it at your sitemap. Set the preload to re-run after the cache lifespan expires.
- Don't purge everything on every edit. Configure the plugin to purge only the changed post plus affected archives — a full purge on every save means your whole site runs cold several times a day.
- Add an object cache (Redis or Memcached) if you run WooCommerce, memberships or anything with logged-in users. It doesn't cache pages, but it makes the uncacheable requests bearable.
Step 2: cache HTML at the edge
By default, Cloudflare and most CDNs cache your images, CSS and JS — but not your HTML. Your TTFB is still your server's TTFB. To fix that on Cloudflare, either:
- Use APO for WordPress (Cloudflare's paid add-on that caches HTML at the edge and purges on publish via the plugin), or
- Create a Cache Rule: eligible for cache when the request doesn't
carry a WordPress session cookie:
…with "Eligible for cache" and an edge TTL of a few hours to a few days. Purge on publish with a plugin like Cloudflare's own or Super Page Cache.(http.host eq "example.com" and not http.cookie contains "wordpress_logged_in" and not http.cookie contains "woocommerce_cart_hash" and not starts_with(http.request.uri.path, "/wp-admin"))
Not sure whether your HTML is actually cached at the edge? Paste a URL into our free
cache checker — if it reports DYNAMIC, your
HTML isn't cached and everything below won't help until it is.
Step 3: warm the edge
Once HTML is cacheable at the edge, you have the second cold-cache problem: hundreds of edge locations, each with its own copy, each starting empty after every purge and TTL expiry. Organic traffic keeps your top pages warm in your top markets — and leaves the long tail cold everywhere else. The math is unforgiving: a site with 500 pages on a CDN with 300 locations has 150,000 cache slots to fill.
This is the part a warming service handles: warmup.rocks reads the same sitemap your caching plugin uses and requests every page through proxies in 40+ countries on a schedule — one request per edge location, so each colo stores its own copy. After every run you see the hit ratio per URL and per location, so you can verify the edge is actually staying warm.
WooCommerce: what you can and can't warm
WooCommerce adds dynamic state — carts, sessions, checkout — and that changes the rules:
- Cache product, category and content pages. They're the same for every anonymous visitor and they're where organic traffic lands. Warm these aggressively.
- Never cache cart, checkout or account pages. Every page cache plugin
excludes them by default; make sure your CDN rule does too (the
woocommerce_cart_hashcookie exclusion above handles it). - Watch the session cookie trap: some setups start a WooCommerce session on the first page view, which sets a cookie and makes every page uncacheable for that visitor. Fix the plugin/theme that triggers the session before warming anything.
- Use AJAX fragments for the mini-cart (WooCommerce does this out of the box) so a cached product page can still show a live cart count.
The payoff is biggest exactly here: a store's long tail of hundreds of product pages is where cold caches cost real revenue — a shopper who waits 3 seconds for a cold product page bounces before your upsell ever renders.
A sane setup, summarized
- One page cache (plugin or host-level) with sitemap preload enabled → server cache warm.
- Object cache (Redis) for the dynamic leftovers.
- CDN caches HTML via APO or a Cache Rule, purge-on-publish wired up.
- warmup.rocks warms every edge location from the same sitemap on a schedule → edge cache warm, verified per colo.
- Check the result with the cache checker: every location
should report
HIT.
Warm every edge location your plugin can't reach
warmup.rocks reads your sitemap and keeps your WordPress HTML warm in 90+ CDN edge locations — with per-location hit-ratio reporting after every run.
Start your 7-day free trial