← Back to blog

How to clear WordPress cache, and how to tell which cache was lying to you

The SandyWP team 6 min read

If a change is not showing up, the fastest honest answer is to purge in order: the caching plugin, then the host's own cache, then the CDN, then the browser. That works, and every guide ranking for this says it.

What they do not say is that purging four layers blindly teaches you nothing, so the next time it happens you start from zero again. One command tells you which layer actually served the page.

curl -sI https://example.com/ | grep -i 'cache\|age\|cf-\|x-litespeed\|x-nginx\|last-modified'

The headers that come back name the culprit. cf-cache-status: HIT with an age is Cloudflare, x-litespeed-cache: hit is LiteSpeed, and x-cache: HIT is usually Varnish or the host's edge.

No cache headers at all, on a page that is still stale, means the cache sits below the HTTP layer. That is a page-cache plugin writing files, a persistent object cache, or PHP's own opcode cache.

Run the same curl twice and compare. If the first response says MISS and the second says HIT, you are watching the layer fill, which is also how you confirm your purge worked.

wp cache flush almost certainly did nothing

This is the one worth knowing, because it is in several of the guides that rank for this phrase, presented as the command that clears the WordPress cache.

wp cache flush calls wp_cache_flush(), which calls WP_Object_Cache::flush(). On a default WordPress install that method is three lines, and the whole of it is this:

public function flush() {
    $this->cache = array();

    return true;
}

$this->cache is a private PHP array, declared on the class and populated during the current request (class-wp-object-cache.php, line 561 in trunk on 2026-10-21). Emptying it discards data that PHP was about to throw away anyway when the process ended.

So the command prints Success: The cache was flushed. and changes nothing a visitor can see. It is not broken, it is doing exactly what it says: it flushes the object cache, and by default the object cache lasts one request.

It becomes a real command the moment wp-content/object-cache.php exists. wp_start_object_cache() in wp-includes/load.php checks for that file and loads it as the external object cache (line 929 in trunk).

With a Redis or Memcached drop-in in place, wp cache flush empties a shared store that survives between requests. That is why the WP-CLI page warns about the performance impact of running it in production, and says nothing at all about the opposite case.

Check which one you have before you trust it:

wp eval 'var_dump( wp_using_ext_object_cache() );'
ls -la wp-content/object-cache.php

false and "no such file" together mean wp cache flush is a no-op on that site.

The five layers, and what actually clears each one

Purge order matters because an outer layer will re-poison an inner one. Work from the visitor inwards.

1. The browser. Yours only, so clearing it proves nothing about what anyone else sees. Test in a private window or with curl instead, and use a hard reload (Cmd-Shift-R or Ctrl-F5) while you work.

2. The CDN or proxy. Cloudflare, a host's edge, Varnish. Purge it from its own dashboard or API, not from WordPress, unless a plugin is explicitly connected to it.

This is the layer people forget, and the one that re-serves the stale page thirty seconds after a successful plugin purge.

3. The page cache. A plugin writing full HTML files, or the host's server-level cache. This is what "clear cache" means in WP Rocket, LiteSpeed Cache, W3 Total Cache and in your host's panel.

4. The object cache. Only exists if wp-content/object-cache.php is there. wp cache flush is the right tool here, and only here.

5. PHP's opcode cache. OPcache holds compiled PHP in the PHP process's shared memory, and no WordPress purge button touches it, because it is not WordPress. It clears on opcache_reset() or when PHP-FPM restarts.

That is why an edited plugin file sometimes keeps running its old code after every cache in the list above has been cleared.

Separating 3 from 5 is what saves the most time. A stale page is layers 1 to 4.

Stale behaviour from a file you just edited, while the page HTML changes correctly, is layer 5.

The trap: a deleted caching plugin that is still caching

Page caching does not run from the plugin. It runs from a drop-in file the plugin installed, and wp-settings.php loads it before plugins exist:

if ( WP_CACHE && apply_filters( 'enable_loading_advanced_cache_dropin', true ) && file_exists( WP_CONTENT_DIR . '/advanced-cache.php' ) ) {
    include WP_CONTENT_DIR . '/advanced-cache.php';
}

That is line 98 of wp-settings.php in trunk, read 2026-10-21. Two things follow from it.

If someone deletes a caching plugin over FTP rather than deactivating it, advanced-cache.php and object-cache.php stay behind. The drop-in keeps serving cached pages with nothing left in the admin to purge it, and the plugin list looks clean.

If define( 'WP_CACHE', true ); was removed from wp-config.php but the drop-in is still there, the opposite happens: the page cache is silently off, the plugin's settings screen still shows it as on, and the site is slow for no visible reason.

Check both when the numbers do not match the settings:

ls -la wp-content/advanced-cache.php wp-content/object-cache.php
grep -n WP_CACHE wp-config.php

When clearing the cache is the wrong answer

If purging makes the problem go away for a few minutes and it returns, the cache is not the bug. Something is writing the wrong output and the cache is faithfully storing it.

The common version of this is a cached page built for the wrong user state: a logged-in view cached and served to visitors, or a cart or nonce baked into a static page. Clearing the cache resets the symptom and the next request recreates it.

The other version is a URL mismatch. If siteurl and home disagree with the domain being served, caches full of absolute URLs to the wrong host look exactly like a caching bug.

That is a site URL problem, not a cache one.

Caches also hide genuine errors. Turn on WP_DEBUG_LOG and read the log before you purge, because the purge destroys the evidence of what generated the bad page.

Our debug mode feature is a toggle and a log viewer for exactly that, with no hand-editing of wp-config.php.

Why a sandbox is the control for this

Every answer above depends on knowing what the site does with no caching at all, and you cannot get that from a production site you are allowed to touch once.

A fresh SandyWP sandbox has no page cache, no object cache drop-in and no CDN in front of it. If the bug reproduces there, it was never a cache.

If it does not, you know the cache was involved, which is far more than "I purged four things and it went away".

The cloning side matters more than it looks. When the Cloner copies a live site into a sandbox, caches, logs and backups are always skipped, so the copy arrives with the database and files but none of the stale artefacts.

That is the comparison you want: same content, same plugins, zero cache.

And since WP-CLI is preinstalled in every sandbox, you can install a Redis drop-in, watch wp cache flush become a command that does something, and see the difference for yourself rather than taking this post's word for it.

The short version

Purge outside in: CDN, page cache, object cache, then your own browser last and only to check.

Run curl -sI before and after, and read the cache headers. That is the difference between fixing it and clearing everything again next week.

And on a default install, wp cache flush flushes a PHP array that was about to be garbage collected. Check for wp-content/object-cache.php before you count on it.