Edge Cache

The Edge Cache module serves cached pages from a CDN location close to your visitors. When content changes, the CDN is cleared together with the local cache, so it never shows outdated pages.

This is the piece that usually makes CDN page caching impractical for WordPress: a CDN happily caches your HTML, but has no idea when a post update makes it stale. MilliCache Pro solves this by mirroring its flag-based invalidation onto the CDN. Every page is tagged at the edge with the same flags it carries locally, and every local purge triggers the matching edge purge.

Static files ride along: because the pull zone fronts your whole site, CSS, JavaScript, images, and fonts are delivered and cached from the edge too; both providers cache common static file types out of the box. You only need the Asset CDN module when files should live in a pull zone of their own.

Enable it under Settings → MilliCache → Modules → Edge Cache (Content Delivery group).

Note: Edge Cache is currently in Beta.

Supported Providers#Copied!

Provider Tagging header Purge granularity
bunny.net CDN-Tag By tag (wildcard), by URL, full zone
Cloudflare Cache-Tag By tag (exact), by URL/prefix, full zone

How It Works#Copied!

flowchart LR
    subgraph "Page served"
        A[Cacheable response] --> B[Tag headers emitted<br/>with MilliCache flags]
        B --> C[CDN stores page<br/>with tags + TTL]
    end
    subgraph "Content changes"
        D[Local cache cleared<br/>by flag] --> E[Matching edge purge<br/>queued at shutdown]
        E --> F[Background purge<br/>via Action Scheduler]
    end

Tagging: when MilliCache serves a cacheable page, the module emits the page's cache flags as CDN tags (for example post:123, home, archive:post), plus a Cache-Control: s-maxage header matching MilliCache's own TTL, so edge copies expire together with the local cache.

Purging: the module listens to every MilliCache invalidation event, including entry expiry, post updates, attachment deletions, and full clears. Purges collected during a request are coalesced into a single background job (a full-zone purge makes narrower ones redundant) and dispatched through Action Scheduler with automatic retries.

Personalized responses stay personal: only the anonymous, cacheable response is edge-cached. Responses that vary per visitor (logged-in users, cookie-based variants, cache buckets) are marked Cache-Control: private, so the CDN never stores them. The other half of the protection lives in your zone configuration: CDNs ignore cookies when serving an already-stored page, so the provider setups below include a cookie bypass that keeps the edge from serving the anonymous copy to a logged-in visitor. Do not skip that step.

Setup: bunny.net#Copied!

  1. Create a pull zone for your site in the bunny.net dashboard.
  2. In the pull zone's caching settings, set Cache Expiration Time to "Respect Origin Cache-Control", so pages expire together with the local cache.
  3. Keep "Strip Response Cookies" off. It is on by default, and with it on, logins break because the zone swallows WordPress's login cookies.
  4. Do not enable "Vary Cache by Request Headers": bunny.net disables tag and URL purging when it is on, which would leave only full-zone purges.
  5. Add an Edge Rule that bypasses the cache for logged-in visitors, so they always reach your server instead of a stored anonymous page: set the action to "Override Cache Time" with 0 seconds, and add a Request Header condition on the header Cookie with the value *wordpress_logged_in_*. Add *wp-postpass_* and *comment_author_* as further values of the same condition (match any).
  6. In MilliCache, select bunny.net as the provider, then enter:
    • API key: your bunny.net account API key (Account Settings → API). Stored encrypted; used only to purge your pull zone.
    • Pull zone ID: the numeric ID of the pull zone that fronts this site.
  7. Click Test connection. A Connected badge confirms the zone is reachable.
  8. Point your site's DNS at the pull zone and enable the module.

Setup: Cloudflare#Copied!

  1. In the Cloudflare dashboard, create an API token with the Zone Read and Cache Purge permissions for your zone (My Profile → API Tokens).

  2. Copy the Zone ID from the zone's Overview page (under API).

  3. Cloudflare only caches pages when a Cache Rule makes HTML eligible. Add one for this site with Edge TTL set to "Use cache-control header if present, bypass cache if not": only pages MilliCache marks cacheable are stored, and they expire together with the local cache.

  4. In the same Cache Rule, exclude requests that carry WordPress auth cookies. Cloudflare ignores cookies when serving a stored page, so without this exclusion a logged-in visitor gets the anonymous copy (no admin bar, no personalization). Use a custom filter expression like:

    (http.host eq "example.com"
    and not http.cookie contains "wordpress_logged_in_"
    and not http.cookie contains "wordpress_sec_"
    and not http.cookie contains "wp-postpass_"
    and not http.cookie contains "comment_author_")
    

    Running a shop? Exclude its session cookies the same way (for WooCommerce: woocommerce_items_in_cart and woocommerce_cart_hash).

  5. In MilliCache, select Cloudflare as the provider, enter the API token and Zone ID, and click Test connection.

  6. Enable the module.

Note: Tag-based purging ("purge by Cache-Tag") is available on all Cloudflare plans. The Free plan rate-limits purge calls; MilliCache retries rate-limited purges automatically with increasing delays.

Behind a Host CDN (Kinsta and Similar)#Copied!

Some hosts route every site through their own Cloudflare layer: Kinsta does for all sites, WP Engine on its Advanced Network and Global Edge Security offerings, and hosts built on Cloudflare Enterprise (Rocket.net, Cloudways with the Cloudflare add-on) likewise. When your own Cloudflare zone sits in front of such a host, traffic passes through two Cloudflare zones in a row; Cloudflare calls this topology Orange-to-Orange (O2O). In it, tag purging silently breaks: Cache-Tag is a Cloudflare-internal header, so the host's Cloudflare consumes and strips it from the response before it reaches your zone, the layer actually caching your pages. Pages are then stored untagged, and tag purges succeed at the API but match nothing, leaving stale pages at the edge until the TTL expires.

To check whether you are affected, compare a tag purge with a URL purge on a cached page: wp millicache edge purge --flag=post:123 has no effect, while wp millicache edge purge --uri=https://example.com/sample-post/ clears it instantly.

The fix takes two steps:

  1. In MilliCache, enable Host CDN compatibility in the Edge Cache settings (shown when Cloudflare is the provider). MilliCache then emits its tags under the neutral MilliCache-Edge-Flags header, which passes through the host's CDN untouched.
  2. In your Cloudflare zone, convert that header back into cache tags: go to Caching → Cache Rules, open the Cache Response Rules tab, and create a rule matching all incoming requests with the action Modify cache tagsOverride existing tagsParse from response header, header name MilliCache-Edge-Flags, separator , (comma). Cache Response Rules are available on every Cloudflare plan.

Clear the cache once after enabling the toggle, so existing entries are re-stored with the new header. If you prefer visitors not to see the tag list, add a second action to the same rule that removes the MilliCache-Edge-Flags response header after parsing.

Settings#Copied!

Setting Provider Description
Provider both The CDN whose edge MilliCache tags and purges
API key bunny.net Account API key, stored encrypted
Pull zone ID bunny.net Numeric ID of the pull zone fronting this site
API token Cloudflare Token with Zone Read and Cache Purge permissions, stored encrypted
Zone ID Cloudflare The zone's ID from its Overview page
Host CDN compatibility Cloudflare Emits tags under a header that survives a host's own CDN layer; see Behind a Host CDN
Test connection both Saves and verifies the credentials against the provider API

On multisite, Edge Cache is configured in the Network Admin: one shared pull zone fronts the whole network. Tags are automatically site-prefixed (2:post:123), so purges stay isolated per site even though every site's pages share one zone.

WP-CLI#Copied!

Command Description
wp millicache edge status Show provider, configuration, and enabled state
wp millicache edge test Test the configured credentials against the zone
wp millicache edge purge Purge edge objects synchronously

purge options:

Option Description
--all Purge the entire pull zone
--flag=<flag> Purge every edge object tagged with this MilliCache flag (e.g. post:123, home); accepts a comma-separated list
--uri=<uri> Purge a specific media URL; a trailing * requests a prefix purge; accepts a comma-separated list

Examples:

 1wp millicache edge purge --all
 2wp millicache edge purge --flag=post:123,home
 3wp millicache edge purge --uri=https://example.com/wp-content/uploads/a.jpg

Unlike runtime invalidation (which is queued in the background), CLI purges run synchronously.

Developer Filters#Copied!

Filter Purpose
millicache_edge_ttl Override the edge TTL in seconds; return 0 to emit no TTL header and let the zone configuration govern expiry
millicache_edge_tag_flags Prune or adjust the flags emitted as edge tags
millicache_edge_variant_vary Opt a response variant into edge caching by returning a Vary header name (only effective on providers that honor response Vary; the current providers do not, so variants stay private)

Notes#Copied!

  • Rate-limited purges are retried automatically (three attempts in total, with increasing delays). If a purge is still rate-limited after the final attempt, the edge copy is left to expire by its TTL.
  • While edge purges are pending, cache preloading batches wait, so pages are never rewarmed through a stale edge.

Next Steps#Copied!

Last updated: