Skip to content

Purging

Gaurav Tiwari edited this page Sep 28, 2026 · 2 revisions

Purging

What a content change removes from the cache, how to see that before it happens, and how to purge by hand. A purge covers the origin page cache first, then the edge: xCloud's host caches when that integration is on, and Cloudflare when it is connected and xCloud does not own the edge.

The policy for publishing and updating

Page Cache > Automatic cache clearing > Cache clearing after publishing (cache.post_publish_purge) decides what an update to a public post purges:

Option Value Purges
Post and related pages (recommended) related The related-URL set below, plus every page whose recorded dependencies say it showed the post
Post URL only post The post's permalink
Entire page and edge cache all Everything, origin and edge, followed by a warm run when warming is on
Do not clear automatically none Nothing on publish or update

The policy covers publishing and editing a public post. Revisions, auto-drafts and posts that are not publicly viewable are ignored. The purged related set (not the dependency matches) is then queued for preloading, public variant only.

The related-URL set

For related, the conservative set is:

  • the post's permalink
  • the home page
  • the post type archive (for posts, the posts page)
  • the author archive
  • the archive of every term the post has in a public taxonomy

Any of these that a filter points at another host (an author URL on a personal domain, for example) is dropped. Only hosts this site answers to are purged, so a foreign URL never reaches the edge purge.

Dependency-aware purging

The related set cannot see a post in a query loop, a "latest posts" grid, a widget, or on page 3 of a category. So while a cacheable page renders, GT Performance records what it was built from, and stores those records in the gtperf_dependencies table:

Signature Recorded when a page Purged when
post:<id> showed that post, or embedded that reusable block or navigation menu that post, block or menu changes
term:<id> ran a query limited to that term a post joins or leaves the term
pt:<type> ran any other query over that post type (* for several) a post of that type is published, withdrawn, re-dated, reordered, or changes terms
ptv:<type> ordered posts by something any edit can change (modified date, comment count, meta value, random) any change to a post of that type
broad:* recorded more than 300 dependencies, or ran more than 200 queries anything changes

Queries are collected at pre_get_posts, so get_posts() and the Latest Posts block count even though they suppress filters. Paginated archive pages record the same listing signatures as page 1, which is how a new post pushes the right later pages out of the cache.

On publish and update, with the related policy only:

  • Content edits. Pages that showed the post, or listed its type in an order an edit can change.
  • Publishing, re-dating, reordering, re-parenting. Every listing the post joins or leaves, including later pages of those listings.
  • Child pages. A change to a page with a parent also reaches pages recorded against the parent.

Under any policy except none, while the page cache is on:

  • Term changes. When a published post moves between terms, both the archive it joined and the archive it left, plus pages that list either term.
  • Term renames. The term's old archive URL and its new one, plus pages that list the term.
  • Reusable blocks and navigation menus. Pages that embed the edited wp_block or wp_navigation post. Neither has a public URL of its own.
  • Sticky changes. Listings the post appears in.

Withdrawals, deletions and comments always include the dependency matches (see the next section).

Dependency purges add to the related set; they never replace it. They are purged but not preloaded (there can be hundreds), and visitors or stale revalidation refill them. One change purges at most 500 dependent URLs.

The records belong to the settings generation they were stored under. After a save that advances the generation (one that changes a setting reaching cached pages; see Page Cache), only pages stored since then have records, and the related set covers the rest. Old rows are pruned by the queue runner.

Changes that purge regardless of the policy

Change Purges
A published post is unpublished, made private, scheduled or trashed Its permalink, the home page, its post type archive, and every page that recorded it or a listing it was in
A published post is permanently deleted The same set. Emptying the trash does not purge again
A post's slug or parent changes Its old permalink, which would otherwise keep serving a 200 ahead of WordPress's redirect
A comment is posted, edited, approved, unapproved or deleted The same set as an unpublished post. Deleting a spam or trashed comment purges nothing
A menu is saved, the theme is switched, the Customizer is saved Everything
WordPress core, a plugin or a theme is updated Everything. Updated code ships new asset versions and often new markup. Translation updates and installing a new plugin or theme do not purge
Settings are saved in the admin and a setting that reaches cached pages changed Everything (the save also moves to a new cache generation). Saving only output-neutral settings, such as credentials, warming, the database schedule or the AI settings, purges nothing. The list is on Page Cache
A product's price, stock or sale status changes through the store's own tools Immediately, at the origin and at the edge: the product (and its parent, for a variation), the home page, the product archive (WooCommerce's shop page) and the product's category and tag archives. Listings found through recorded dependencies follow as queued purges. See Commerce Safety

Previewing a purge

See what an update would purge, and why, without purging anything:

wp gt-performance cache preview --post=123
wp gt-performance cache preview --post=123 --membership

--membership previews a publication, withdrawal or term change instead of a content edit. The output names the active policy and change type, then lists each URL with its reasons:

Reason Meaning
permalink, home, post type archive, author archive, term archive: <name> Part of the related-URL set
recorded dependency: shows post <id> The page displayed the post (or embeds it)
recorded dependency: lists term <id> The page lists that term
recorded dependency: lists <type> posts The page lists that post type
recorded dependency: lists <type> posts in an order any edit can change Volatile ordering
recorded dependency: too many dependencies to record individually The page recorded broad:*

The last line reports how many pages have recorded dependencies under the current generation. Under all the preview says everything would be purged; under none it lists nothing. AI assistants with agent access can run the same preview through the gt-performance/preview-purge ability. See AI and MCP.

Manual purges

Where Action Does
Dashboard > Operations Purge GT cache Every stored page, then a full edge purge (this site's hostnames at Cloudflare). Waits for Cloudflare before reporting
Admin bar > GT Performance Purge this URL The current page (and its mobile variant), then that URL at the edge
Admin bar Purge and verify this URL Purge, then a verified receipt (below)
Admin bar Warm this URL Requests the current page with X-GT-Preload, which rebuilds it when it is missing or stale
Admin bar Purge page and edge caches Same as Purge GT cache
WP-CLI wp gt-performance cache purge Everything, origin and edge
WP-CLI wp gt-performance cache purge --page-url=<url> One URL, origin and edge
WP-CLI wp gt-performance cloudflare purge [--page-url=<url>] Cloudflare only: this site's hostnames, or one URL

The admin-bar menu appears for users who can manage_options. The per-URL items appear on front-end pages of this site only. A full purge starts a warm run when warming is on.

Use --page-url, not --url: WP-CLI reserves --url for choosing a site. AI assistants with operate permission can purge up to 20 URLs per request through the gt-performance/purge-urls ability, but never the whole site.

Verified purge receipts

A 200 after a purge proves little. Purge and verify this URL, or:

wp gt-performance cache verify --page-url=https://example.com/pricing/

inspects the origin entry, purges the URL at the origin and the edge, waits for the edge purge, then requests the URL publicly twice. The receipt is verified only when:

  • the origin entry is gone after the purge
  • both public responses are HTTP 200 and not marked private
  • the two bodies match
  • with Cloudflare connected, the first response was not an old HIT or STALE with a positive Age

Anything else is warning. An edge purge that fails produces a failed receipt with the error. The last 20 receipts are kept, and Tools > Verified purge receipts shows the 10 newest. The health report flags the latest one when it is not verified. See Diagnostics and Tools.

Query variants

Pages cached separately per value of a parameter (Cache each value separately, see Page Cache) are recorded in a per-page index. Purging the page's URL, by any route above, deletes every recorded variant at the origin and adds the variants' full URLs to the edge purge, so a sorted or filtered listing never outlives an edit to its page.

Device variants

With Separate cache for mobile HTML on:

  • An origin URL purge deletes both the public and the mobile entry.
  • A Cloudflare URL purge sends the plain URL plus desktop, mobile and tablet device keys (CF-Device-Type), matching the managed rule's cache-by-device-type setting.
  • A warm run queues the mobile variant explicitly. Post-publish preloads and stale revalidation refresh the public variant only.

How purges reach the edge

Purges triggered during a request are collected and sent to Cloudflare once, at shutdown, 100 cache keys per API call. Manual actions and verification flush the batch first so they can report the real result. Transport errors, rate limits and 5xx responses are retried up to three times through WP-Cron, keeping the unprocessed entries and honoring Retry-After.

A full purge at Cloudflare purges this site's canonical hostnames (the hosts of home_url() and site_url(), plus any added with gt_performance_canonical_hosts), not the whole zone, so other sites and subdomains that share the zone keep their cache. Purge by hostname works on every Cloudflare plan. A successful full purge supersedes pending URL retries. Every Cloudflare sync, including the one Setup runs, also purges this site's hostnames after writing the rule. The latest result is on the Cloudflare tab. See Cloudflare.

The xCloud integration runs at most one host-cache purge per request, whether one URL or everything changed. See xCloud.

The edge integrations load on admin, cron, AJAX, REST and WP-CLI requests and for signed-in users, and on any other request the moment a purge fires. So a purge from a signed-out visitor's request, such as a comment WordPress approves on the spot or a classic WooCommerce checkout that sells a product out, reaches Cloudflare and xCloud as well as the origin.

Price, stock and sale changes purge the product, the shop page and the product's categories within the request. The listings found through recorded dependencies go through the background queue as purge_url jobs, since a bulk stock sync can touch thousands of products. Those jobs keep running when optional queue work is paused.

Same-site restriction

Purges are kept to this site:

  • The related-URL set drops any URL whose host this site does not answer to.
  • --page-url for wp gt-performance cache purge, cache explain, cache verify and cloudflare purge must be a complete http(s) URL on one of the site's canonical hosts (the hosts of home_url() and site_url(), plus any added with the gt_performance_canonical_hosts filter). Anything else is refused before it is fetched or handed to the edge.
  • The admin-bar actions, Tools > Explain this page, cache explain and cache verify go further and accept only the home host.
  • The AI abilities reject any URL that is not a public http(s) URL on this site.
  • The queue refuses to request or purge a URL whose scheme, host or port does not match the site, even when the job row was written by an earlier release.

Related

Page Cache · Cache Warming · Commerce Safety · Cloudflare · Diagnostics · WP-CLI

Clone this wiki locally