Site Changes Not Showing? Fix Cloudflare Cache Issues

· 6 min read · 27 views · Getwebup

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=123 to 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:

LayerWhat it storesWho controls it
Browser cacheA copy saved on the visitor's own deviceThe visitor (or your Cache-Control headers)
Cloudflare edge cacheA copy at Cloudflare's nearest data center to the visitorYou, via the Cloudflare dashboard or API
Server-side cacheLiteSpeed 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

  1. Log in to the Cloudflare dashboard and select the domain.
  2. Go to Caching → Configuration.
  3. 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.
  4. 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.
  • MISS or EXPIRED – Cloudflare fetched a fresh copy from your origin. This is what you want right after a purge.
  • DYNAMIC or BYPASS – 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-status with curl -sI whenever "it's not updating" comes up — it tells you in one line whether Cloudflare, your browser, or a plugin is holding the old copy.

Questions people actually ask