PURGE
PURGE is an operator- or API-triggered invalidation that removes cached objects from a CDN edge before their TTL ends, so the next request misses and refetches from origin. Scopes run from one URL or cache tag to a prefix or the whole cache. It is not a standard HTTP method.
Also known as Cache purge, Purging, Cache purging.
Full Explanation
A purge is an explicitly requested invalidation. It removes an object from a CDN cache before its TTL ends, so the next request for that object is a miss and the CDN refetches it from the origin. Fastly defines it exactly: purging "explicitly removes content from a cache, rather than allowing it to expire or to be evicted". Later requests then "proceed to origin as a cache miss". Purge is therefore the operator-driven counterpart to the two things it is not. Expiry is the clock running out. Eviction is the CDN reclaiming space on its own.
PURGE is also not part of HTTP. It does not appear in the IANA HTTP Method Registry. MDN notes that "the HTTP Caching specification essentially does not define a way to explicitly delete a cache". HTTP does define invalidation, but only as a side effect of unsafe methods. RFC 9111 section 4.4 requires a cache to invalidate the target URI after a non-error response to a PUT, POST or DELETE. It notes that "a state-changing request would only invalidate responses in the caches it travels through" rather than everywhere. Purge fills that gap. Each CDN fills it its own way. Fastly and Cloudflare both brand theirs Instant Purge. Amazon CloudFront calls the same operation an invalidation. Varnish answers a PURGE request only if you write the VCL for it. No purge reaches a visitor's browser. RFC 9111 section 1 defines a private cache as one "dedicated to a single user". An edge purge cannot touch it.
How it works
A cached object is served without asking the origin. This continues until its freshness lifetime ends or it is evicted. A purge cuts that short. You name the set to remove, and the CDN distributes the instruction to its cache servers. The scopes below go in increasing blast radius:
- Single URL. This removes the object stored under one URL's cache key. On Fastly that is an API call or an HTTP PURGE request sent to the URL itself. Inside CDN services, the method is rewritten to FASTLYPURGE before your configuration sees it. Because it targets the cache key, a Fastly URL purge invalidates every variant of the object.
- Tag or key. The origin stamps responses with a Surrogate-Key (Fastly) or Cache-Tag (Cloudflare) header. Purging the tag removes every object carrying it. One key can sit on many objects, and one object can carry many keys. So a single call clears a logical group, such as every page that mentions one product, without you knowing the URLs. Both CDNs strip the header before the response reaches the visitor.
- Prefix, hostname or pattern. Cloudflare purges by URL prefix or by hostname. CloudFront takes an invalidation path ending in an asterisk. That asterisk "must be the last character in the invalidation path". Varnish calls pattern invalidation a ban. A ban filters objects already in cache and is evaluated lazily on lookup. Self-run nginx has a proxy_cache_purge directive. There, a purge key ending in an asterisk removes all matching entries. But that directive is not in open-source nginx: nginx.org states "This functionality is available as part of our commercial subscription."
- Everything. Purge-all discards every cached object for the service or zone.
Each scope comes in two strengths. A hard purge is the default. It makes the object "immediately inaccessible to new requests". The bytes may sit on disk until eviction, but no cache lookup will match them again. A soft purge instead "marks the affected object as stale rather than making it inaccessible". So the copy stays usable for conditional revalidation and stale serving. On Fastly, soft purge covers URL and surrogate-key purges. It does not cover purge-all, which always invalidates immediately.
Propagation is a distributed operation, not an atomic one. Fastly pushes URL and surrogate-key purges out from the receiving POP using "a variant of a gossip protocol". This takes "around 150ms to reach every cache server in the network". Purge-all works differently. Fastly recompiles the service configuration to increment a cache generation number that feeds the cache key. So identical requests before and after the purge hash differently, and the old generation falls out of reach. That is why purge-all "operations take up to 2 minutes to complete". That is also why it is the only Fastly purge that can be reversed at all.
Why it matters for a CDN
A CDN keeps copies at hundreds of points of presence. HTTP gives the origin no way to reach out and revoke them. Without purge, your only lever is the clock. So correctness forces short TTLs. Short TTLs cost you cache hit ratio and add origin traffic. Purge breaks that trade. Set a long Cache-Control lifetime and invalidate on change instead. Fastly names the pattern directly, recommending "setting a very long TTL in a Cache-Control header so that traffic to origin is minimized, but end users are still assured of up to date content". Tagging is what makes it affordable at scale. One key purge replaces thousands of URL purges. That is the difference between usable and unusable for a CMS whose single edit touches many pages, or an API whose one record appears across many endpoints. Fastly rates the surrogate-key purge "the most powerful, flexible, and performant" of its types. It calls surrogate-key purge "on average, 100x faster than a purge-all".
What CDNs do
- Fastly offers purge-all, URL and surrogate-key purges through its web interface, API and CLI, with surrogate-key purges also callable from edge code. A batch request can carry up to 256 keys. URL and key purges support soft purge; purge-all does not. URL and key purges are not counted against API rate limits. They are capped at "an average of 100,000 purges per hour, per customer". Purge-all counts against the global API limit and is the only purge type logged automatically.
- Cloudflare brands its purge Instant Purge. It offers single-file, prefix, hostname, cache-tag and purge-everything operations. Its availability table lists all of them on every plan, including Free. What changes with the plan is the rate. Purge requests draw on per-account token buckets. These range from 5 requests per minute with a bucket of 25 on Free, to 50 per second with a bucket of 500 on Enterprise. A tag, prefix, hostname or purge-everything request carries at most 100 operations. Cloudflare recommends single-file purge as the default method. Single-file purge sets CF-Cache-Status: MISS on subsequent requests.
- Amazon CloudFront calls the operation an invalidation and charges for it. "The first 1,000 invalidation paths that you submit per month are free". After that, every path is billed, with a wildcard path counting as one. AWS accordingly recommends versioned file names over invalidation for files you update often.
- Self-run caches expose nothing by default. Varnish answers a PURGE request only if your VCL checks the method and calls return(purge). That purge "will remove all variants as defined by Vary". Regex matching belongs to a separate mechanism, the ban. nginx needs the commercial proxy_cache_purge directive.
Watch out for
- A wide purge is a load test on your origin. Fastly warns that "Purging a large amount of content from a high traffic service is likely to result in a rapid increase in traffic to origin". It also warns that a purge-all "may temporarily increase your website's load time while the cache rebuilds". Many edges refilling the same objects at once is a cache stampede.
- An open purge endpoint is an origin-load weapon. On Fastly, "URL purges are unauthenticated by default". Requiring a token means setting the request header Fastly-Purge-Requires-Auth to 1 in your service configuration. Varnish ships no purge handling at all. Its own documentation pairs return(purge) with an ACL that limits who may call it.
- Purge does not reach browsers. Each visitor holds a private copy governed by the response you already sent. AWS states the consequence plainly. After an invalidation, "the user might continue to see the old version until it expires from those caches".
- Shielding can undo a purge. "Since the order in which caches are purged is not deterministic", a request can reach a purged edge POP. That request can be forwarded to an origin shield POP that has not been purged yet, and repopulate the edge with pre-purge content. Fastly's blunt fix is "simply to purge twice". Purge about 30 seconds apart for purge-all, and about 2 seconds apart for URL and key purges. The tidier fix is to compare the cache generation value between shield and edge in edge code.
- Custom cache keys are where purges silently fail. Cache Rules can build a Cloudflare cache key from headers or cookies. If they do, "single-file purge via the dashboard will not invalidate the cached resource", because the dashboard cannot send those values. The API can send them, if you pass every header and cookie that is part of the key. Dashboard single-file purge also skips objects cached with an Origin, X-Forwarded-Host, X-Host, X-Forwarded-Scheme, X-Original-URL, X-Rewrite-URL or Forwarded request header. A Cache Rule that matches only GET will not match a purge at all, unless you add the PURGE method to its expression. Vary is the other reason one URL can hold several stored objects.
- Case and wildcard rules differ by vendor. "Surrogate keys are case sensitive" on Fastly, and CloudFront invalidation paths are case sensitive too. Cloudflare cache-tags are not case sensitive. "Wildcards are not supported on single file purge" at Cloudflare. So a pattern there means purge by prefix, hostname or tag.
- Most purges cannot be undone. Fastly is explicit: "It is not possible to revert a URL purge or a surrogate key purge." A purge-all can be reverted by decrementing the cache generation. But only Fastly staff can do that, through support, and only in part. "Reverting a purge does not guarantee that all previously cached content will return."
Best practice
- Pair a long Cache-Control lifetime with a purge on change. That pairing is the reason to run a long TTL at all. Without the purge, you are only guessing at a TTL that is safe.
- Tag first, then purge narrowly. Fastly's own advice: "If you find yourself purging all cache on more than a weekly basis, consider using surrogate keys for more targeted purging."
- Authenticate the purge surface. Keep the right to call it scoped to the systems that need it. Treat a purge credential as a production credential.
- Give an object something to revalidate with before you rely on soft purge. Fastly recommends one of two things, not both. Use ETag or Last-Modified headers from the origin, or use stale-while-revalidate. If you pick stale-while-revalidate, you must configure stale-if-error alongside it.
- For hashed or immutable assets, change the URL instead of purging. Cache busting lets old pages keep loading the files they were built with. Fastly warns that a purge-all "will also remove all versioned assets".
- Purge the key that was actually cached. Most reports of a purge doing nothing are cache-key mismatches: a rewritten URL, a changed hash function, a transformed path, or a query string left out of the purge request.
Examples
# Cloudflare: purge single URL
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone}/purge_cache" \
-H "Authorization: Bearer {token}" \
-d '{"files": ["https://cdn.example.com/style.css"]}'
# Fastly: purge by surrogate key
curl -X POST "https://api.fastly.com/service/{id}/purge/product-123" \
-H "Fastly-Key: {token}"
# Varnish: PURGE method
$ curl -X PURGE https://cdn.example.com/style.css
# Varnish VCL: ban (regex purge)
ban req.url ~ "^/static/.*\.css$"
# Nginx: proxy_cache_purge
location /purge {
proxy_cache_purge cache_zone $uri;
}
Frequently Asked Questions
PURGE is an operator- or API-triggered invalidation that removes cached objects from a CDN edge before their TTL ends, so the next request misses and refetches from origin. Scopes run from one URL or cache tag to a prefix or the whole cache. It is not a standard HTTP method.
# Cloudflare: purge single URL
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone}/purge_cache" \
-H "Authorization: Bearer {token}" \
-d '{"files": ["https://cdn.example.com/style.css"]}'
# Fastly: purge by surrogate key
curl -X POST "https://api.fastly.com/service/{id}/purge/product-123" \
-H "Fastly-Key: {token}"
# Varnish: PURGE method
$ curl -X PURGE https://cdn.example.com/style.css
# Varnish VCL: ban (regex purge)
ban req.url ~ "^/static/.*\.css$"
# Nginx: proxy_cache_purge
location /purge {
proxy_cache_purge cache_zone $uri;
}
Yes. PURGE is also known as Cache purge, Purging, Cache purging. PURGE is an operator- or API-triggered invalidation that removes cached objects from a CDN edge before their TTL ends, so the next request misses and refetches from origin. Scopes run from one URL or cache tag to a prefix or the whole cache. It is not a standard HTTP method.
Related CDN concepts include:
- Surrogate Key / Cache Tag — A surrogate key, or cache tag, is a label the CDN indexes against a cached …
- Cache Busting — Giving a web asset a new URL whenever its content changes, so every cache treats …
- Cache-Control — Cache-Control is the HTTP header field, defined in RFC 9111, that carries caching directives to …
- Stale Content — Stale content is a cached response whose freshness lifetime has passed. RFC 9111 forbids serving …
- TTL (Time To Live) (TTL) — TTL (time to live) is how many seconds a cached response stays fresh before a …