Site Changes Not Showing? Fix Cloudflare Cache Issues
You fixed the typo, uploaded the new banner, or rolled out a price change an hour ago — and your visitors are still looking at the old page. You've cleared your browser cache twice, tried incognito, even called a friend to check. Nine times out of ten on a Cloudflare-fronted site, the culprit isn't your server or your browser. It's Cloudflare's edge cache holding onto the previous version of the page.
Symptom: The Change Is Live on the Server, But Not on the Site
Here's the giveaway pattern support tickets usually show:
- You can see the correct, updated content when you view the file directly in cPanel's File Manager or over SSH.
- Loading the page from a mobile network (not your home Wi-Fi) still shows the old version.
- Adding a random query string like
?v=123to the URL suddenly shows the new content. - The change appears for you but not for anyone else — or the other way around.
That last symptom is the clearest sign of edge caching: Cloudflare has dozens of data centers (PoPs) worldwide, and each one caches a copy independently. The PoP nearest you might have already refreshed while the one serving a visitor in another city hasn't.
Why Cloudflare Is Holding an Old Copy
There are three separate caches between your origin server and a visitor's screen, and it's easy to purge the wrong one:
| Layer | What it stores | Who controls it |
|---|---|---|
| Browser cache | A copy saved on the visitor's own device | The visitor (or your Cache-Control headers) |
| Cloudflare edge cache | A copy at Cloudflare's nearest data center to the visitor | You, via the Cloudflare dashboard or API |
| Server-side cache | LiteSpeed Cache, WP Super Cache, Redis object cache, PHP OPcache, etc. | You, via the plugin or service php-fpm reload |
If you only clear your WordPress caching plugin and skip Cloudflare, the edge still serves the stale HTML it cached before your edit. If you only purge Cloudflare and your origin's Cache-Control header says max-age=86400, browsers that already loaded the page once will sit on the old copy for a full day regardless.
Quick Fix: Purge Cloudflare Right Now
- Log in to the Cloudflare dashboard and select the domain.
- Go to Caching → Configuration.
- Click Purge Everything for a full reset, or Custom Purge and paste the exact URL (e.g.
https://example.com/pricing/) if you only need one page cleared. - Wait 30 seconds – purges typically propagate across all PoPs within a minute, occasionally up to five.
If you'd rather not touch the dashboard every time, the API call does the same thing and is easy to script into a deploy or a WP-CLI hook:
curl -X POST "https://api.cloudflare.com/client/v4/zones/<ZONE_ID>/purge_cache" -H "Authorization: Bearer <API_TOKEN>" -H "Content-Type: application/json" --data '{"purge_everything":true}'
Confirm It Actually Worked
Don't just reload the page and eyeball it — check the response header directly:
curl -sI https://example.com/ | grep -i cf-cache-status
You'll see one of these:
HIT– served from Cloudflare's cache. If you just changed the page and still see this, the purge either hasn't finished propagating or didn't target the right URL.MISSorEXPIRED– Cloudflare fetched a fresh copy from your origin. This is what you want right after a purge.DYNAMICorBYPASS– the page isn't being cached at Cloudflare's edge at all, so the problem is elsewhere (browser cache or a plugin cache).
Why the Old Page Keeps Coming Back
Purging once is easy. Stopping it from happening on every future edit takes fixing the actual cause:
A "Cache Everything" Page Rule or Cache Rule
By default Cloudflare only caches static assets (images, CSS, JS) and leaves HTML uncached. If someone added a Page Rule or Cache Rule with Cache Level: Cache Everything to speed up a slow WordPress site, it now caches full HTML pages too — including ones that should never be cached, like /cart/, /checkout/, or anything behind a login.
Automatic Platform Optimization (APO) for WordPress
If APO is turned on, Cloudflare caches your WordPress HTML at the edge automatically and is supposed to auto-purge on publish via the official Cloudflare plugin. If that plugin isn't installed or its API token expired, publishing a post no longer triggers the purge, and old pages linger indefinitely.
Origin Cache-Control headers are too aggressive
Check what your server is actually telling browsers and Cloudflare to do:
curl -sI https://example.com/ | grep -i cache-control
A .htaccess rule or Nginx config left over from a "speed up my site" tutorial can set max-age=31536000 (one year) on HTML pages, not just images. That's fine for a logo, disastrous for a page you edit weekly.
Development Mode was never toggled on
If you're mid-redesign and testing multiple changes in a row, purging after every single edit is tedious. Cloudflare's Development Mode (Caching → Configuration) bypasses the cache entirely for three hours so every request hits your origin fresh — then re-enable normal caching once you're done.
Permanent Fix: Cache Rules That Don't Bite You Later
Instead of a blanket "Cache Everything" rule, scope it so dynamic paths never get cached at the edge:
- In Caching → Cache Rules, create a rule matching your static asset paths only (
*.css,*.js,/wp-content/uploads/*) with a long edge TTL. - Add a second rule that explicitly bypasses cache for
/wp-admin/*,/wp-login.php,/cart/*, and/checkout/*. - Leave everything else on Cloudflare's default behavior — it already knows not to cache dynamic HTML unless you tell it to.
- If you use APO, verify the Cloudflare plugin is active in WordPress and its API token in Settings → Cloudflare hasn't expired — that's what wires up auto-purge on publish.
On the origin side, set sane Cache-Control headers per file type instead of one blanket rule. In your Nginx server block or an .htaccess for Apache:
# Long cache for assets that change with a filename/hash, not in place
location ~* \.(css|js|jpg|png|webp)$ {
add_header Cache-Control "public, max-age=2592000";
}
# Never cache HTML at the browser level
location ~* \.(html|php)$ {
add_header Cache-Control "no-cache, must-revalidate";
}
Prevention Checklist
- Scope any "Cache Everything" rule to static file paths only — never the whole domain.
- Keep
/wp-admin, checkout, and cart URLs on a hard cache bypass rule. - If you run APO, confirm the WordPress plugin's connection is still valid every few months — expired tokens fail silently.
- Turn on Development Mode during active redesign work instead of manually purging after every save.
- Check
cf-cache-statuswithcurl -sIwhenever "it's not updating" comes up — it tells you in one line whether Cloudflare, your browser, or a plugin is holding the old copy.
Frequently asked questions
How long does a Cloudflare purge take to actually apply?
Usually under a minute across all data centers, though Cloudflare's own SLA allows up to about 30 seconds for a targeted purge and a bit longer for Purge Everything on busy zones. If it's been five minutes and curl -sI still shows HIT, the purge request likely didn't go through or the wrong URL was targeted.
I see the new version but a visitor in another city still sees the old one. Why?
Cloudflare caches independently at each of its global data centers. Purge Everything clears all of them, but a Custom Purge on a specific URL sometimes needs the exact URL with and without a trailing slash, and with the correct http/https scheme, to clear every cached variant.
Does Purge Everything affect my DNS or SSL settings?
No. Purging cache only clears cached page content and assets sitting at Cloudflare's edge. It has no effect on your DNS records, SSL/TLS mode, Page Rules, or firewall settings.
I purged the cache and it's still showing the old page. What's next?
Check three things in order: the cf-cache-status header (to confirm Cloudflare actually re-fetched), your browser cache (test in a private window), and any server-side cache like LiteSpeed Cache or WP Super Cache that might be serving a stale copy from your origin before Cloudflare even sees it.
Should I turn on Development Mode every time I edit the site?
Only if you're making several changes in one sitting, like during a redesign. For a single one-off edit, a Custom Purge on that specific URL is faster and doesn't leave your whole site running uncached for three hours.