Cache-Tag

The HTTP Cache-Tag response header is an unofficial header labeling a cached response with one or more identifiers, so a later purge removes every response sharing a label rather than one URL at a time.

Usage

An origin attaches Cache-Tag to a response and Cloudflare stores the labels alongside the cached object. Purging by tag then clears every object carrying the label in a single operation, which suits content appearing across many addresses. A product record rendered on a category page, a search result, and a detail page carries the same tag on all three, so one purge refreshes the set.

The alternative, purging by URL, requires knowing every address where the content appears. Tags move the bookkeeping to publication time, where the rendering code already knows which entities went into the response.

Cloudflare strips Cache-Tag before the response reaches a visitor. Browsers and Workers see nothing, so the header stays a private channel between the origin and the edge. Confirming the value calls for a request straight to the origin, bypassing the proxy.

Values

Tags are comma-separated and accept printable ASCII only, with spaces prohibited inside a tag. Whitespace around a separator is stripped, repeated commas collapse, and matching ignores case, so Tag1 and tag1 address the same objects. A response carries more than one Cache-Tag header where the list grows long.

Cache-Tag: product-1234,category-shoes,homepage

Three limits govern the header:

Limit Value
Tag length in the header no documented maximum
Tag length in a purge API call 1,024 characters
Aggregate header size 16 KB after the field name

The 16 KB budget counts whitespace and commas while excluding the field name, and Cloudflare estimates roughly 1,000 tags inside the allowance. The figure is a gloss on the byte cap rather than a separate count, so the real ceiling tracks tag length.

Exceeding the 16 KB aggregate is the common failure, and generous per-entity tagging on a page assembling hundreds of records reaches the ceiling quickly. Tagging by entity type and identifier rather than by every relationship keeps the header inside the budget.

Example

A product page labels the response with the product, the category, and the template. A change to the category purges every product carrying the same category tag, and a template change purges every page built from the same template.

HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: public, max-age=3600
Cache-Tag: prod-88213,cat-outerwear,tpl-product-v3

Ecommerce platforms in the wild favor short prefixed identifiers rather than readable names. Observed values follow a compact scheme, where each prefix marks an entity type and the number identifies the record.

Cache-Tag: P-20927937,SS-58645295751,PGS-ALL,SW-3

The compactness is deliberate. Short prefixes keep hundreds of tags inside the 16 KB budget, and the purge API matches on exact strings, so readability buys nothing at the edge.

Purging by tag

Purge requests go to the Cloudflare API for the zone, carrying the tags to clear.

POST /client/v4/zones/{zone_id}/purge_cache
Authorization: Bearer <token>
Content-Type: application/json

{"tags": ["prod-88213", "cat-outerwear"]}

Purging by tag is available at Cloudflare. Rate limits and batch sizes vary by Cloudflare account, with a maximum of 100 operations per request. A deployment purging thousands of tags batches them and paces the calls against the account limit rather than firing per entity.

Purged objects return to Cf-Cache-Status MISS on the next request, or EXPIRED where Tiered Cache leaves a lower tier revalidating against an upper one. Propagation is fast enough to treat as immediate, with Cloudflare reporting a median under 150ms globally, ahead of single-URL purging.

Equivalent headers across CDNs

Every major CDN implements the same idea, and three details differ between them: the header name, the separator, and whether the header survives to the browser.

Vendor Header Separator Downstream
Cloudflare Cache-Tag comma always stripped
Netlify Cache-Tag comma always forwarded
Akamai Edge-Cache-Tag comma configurable
Fastly Surrogate-Key space stripped unless debugging

Netlify is the case worth attention, because the header name and separator match Cloudflare exactly while the behavior inverts. Netlify forwards Cache-Tag downstream deliberately, so other caches read the labels, and accepts UTF-8 where Cloudflare accepts printable ASCII alone. Netlify also caps a response at 500 tags and offers Netlify-Cache-Tag, which is stripped and takes priority when both appear.

Stacking the two providers exposes the mismatch. A Netlify origin behind Cloudflare emits tags intended for the browser into a proxy treating the same header as a private purge instruction, and the labels disappear at the Cloudflare edge.

Akamai diverges by name rather than by meaning, and Edge-Cache-Tag caps a tag at 128 characters and a cached object at 128 tags, well below the Cloudflare budget. Only the first Edge-Cache-Tag header on a response is respected, and a 304 response leaves existing tags unchanged.

Crawl data shows platforms hedging. Responses carrying identical comma-separated values in both Cache-Tag and Edge-Cache-Tag appear regularly, which is how one origin serves customers behind either CDN without branching the rendering code.

Migrating tags from another CDN

Cloudflare Cache Response Rules build Cache-Tag from an existing header through the set_cache_tags action, so tagging code written for another CDN survives the move. The translation runs only once configured, with no implicit conversion.

Cloudflare's documented example splits a Surrogate-Keys header on commas. A migration from Fastly needs different values on both counts, since the Fastly header is Surrogate-Key without the plural and separates with spaces. Copying the published example unchanged against real Fastly output produces a single malformed tag rather than a list, and purges silently match nothing afterwards.

Standing outside the registry

Cache-Tag is a vendor convention rather than a registered field, as are Edge-Cache-Tag and Surrogate-Key. Purge-by-label has no standardized header, which is why four vendors arrived at four answers.

A standards-track alternative now exists in Cache-Groups and Cache-Group-Invalidation, which describe group membership and invalidation as registered fields rather than per-vendor headers. Adoption remains early, and vendor tagging carries production traffic today.

Labelling stays orthogonal to cacheability throughout. Cache-Tag marks a stored object for later purging and changes nothing about whether the object is cached or for how long, which remains the work of Cache-Control and the targeted headers.

See also

Last updated: August 18, 2026