Cache: status headers, bypass reasons, purges
How node caching decides: X-CDN-Cache values, the 15 bypass reasons and fixes, the cache key, and how purges and prewarm take effect.
How it works
A request first passes the security checks (access control, WAF, CC); then the cache module decides. A cacheable request is looked up and a hit is answered at once; a request that cannot be cached goes to the origin and is not stored. When the origin answers, the node decides from the response whether to store it.
The cache key holds the site identity, the site's cache generation, the site purge generation, the domain (or the site's main domain, depending on the cache settings), the port, and the path with its query. Whether the query and request headers are part of the key is up to the cache rule (keep, ignore, or keep some parameters; vary by named headers). The same file on another port or domain is therefore a separate cache entry.
The X-CDN-Cache status header
When the site caches and "Show cache status in response headers" is on in the site settings (the default), every response carries X-CDN-Cache. While attack escalation holds the site at level B or above, the control plane turns both headers off so an attacker cannot tell whether requests get past the cache.
| Value | Meaning |
|---|---|
HIT | Served from cache, no origin request |
MISS | Not in cache; fetched from the origin and stored per the rules |
EXPIRED | The cached copy expired; fresh content was fetched |
STALE | Expired, but the origin failed, so the old copy was served as the rule allows |
UPDATING | Expired and being refreshed in the background; the old copy was served |
REVALIDATED | Expired; the origin confirmed it is unchanged, so it stays in use |
BYPASS | The cache was not used this time; see X-CDN-Cache-Reason |
Bypass reasons in X-CDN-Cache-Reason
Request-side reasons are checked in this order; the first that applies wins.
| Reason | When | What to do |
|---|---|---|
method | The method is not GET or HEAD | Expected |
authorization | The request has an Authorization header | Expected; signed-in personal content should not be cached |
cookie | The request has a cookie and no cache rule covers the path | Add a cache rule for static paths; requests a rule covers ignore request cookies |
upgrade | WebSocket and other upgrades | Expected |
search_engine | The site has search engine origin on and a crawler sent the request | Expected: crawlers use their own origin and neither read nor fill the visitors' cache |
no_cache_rule | No cache rule covers the request, or the rule caches no response with this status | Check the rule's paths, extensions and status codes |
no_cache_condition | A "do not cache" condition of the matching rule holds | Check the conditions |
key | No cache key could be built: the query is over 8 KiB or 256 parameters, a key header is over 4 KiB or all key headers over 16 KiB, percent-encoding is invalid, or the path does not start with / | Shorten the query, or have the rule ignore unrelated parameters |
purge_state | The node just started and has not loaded the sites' purge generations | Expected; it clears once they are loaded. Nothing is cached meanwhile so purged content cannot come back |
disabled | Caching is off for the site | Turn it on in the cache settings |
Response-side reasons are checked once the origin answers:
| Reason | When | What to do |
|---|---|---|
set_cookie | The origin response has Set-Cookie | Do not set cookies on static files |
origin_no_store | The origin's Cache-Control has private, no-store or no-cache | Change the origin's Cache-Control |
object_size | The response size is outside the rule's minimum and maximum object size | Adjust the rule's size range |
content_type | The response Content-Type is not one the rule allows | Adjust the rule's content types |
response_rule | A site response rule replaced this response (such as an error page) | Expected: replaced responses are never stored |
Purge and prewarm
| Operation | How it takes effect | Time |
|---|---|---|
| Purge URL | The node deletes the file by its cache key | Usually immediate. On sites whose key includes the query or request headers, the node scans cache files, as for a directory purge |
| Purge directory (including wildcard domains) | The node finds the site's files under the path in the cache partition holding the site and deletes them | With the cache index (the default), a few seconds for a 300,000-file partition; while the index is building or unavailable the whole partition is scanned, about 3 minutes cold for 1 million files |
| Purge site | The node increments the site's purge generation, so later requests miss the old content at once; old files are deleted in the background | Immediate for visitors |
| Prewarm | Each node fetches the addresses from the origin once and stores them | Depends on the origin and the file sizes |
- One submission takes up to 500 addresses. URL purges, directory purges and prewarms each have a daily quota per account (shared by all members and sites of the account), counted per calendar day in Beijing time; a site purge counts as one directory purge.
- Each node runs its purge and prewarm tasks one at a time, so a slow directory purge delays the tasks behind it. A task runs for at most 1 hour.
- Without named nodes, a task goes to every node serving the site; a node that starts serving the site within 24 hours repeats the same task automatically.
- Expired content stays on disk for up to 24 hours for "serve stale when the origin fails".
Common questions
Always MISS or BYPASS
Read X-CDN-Cache-Reason first. The usual causes are cookie (the request has a cookie and the path has no cache rule) and set_cookie or origin_no_store (the origin forbids caching). With MISS rather than BYPASS, requests may reach different nodes: each node has its own cache and fetches from the origin the first time.
Old content after a purge
Check that the purge succeeded on every node (the operation history shows each node's result). Browsers cache too; try another browser or add a different query parameter.
Visitors still reach the origin after a prewarm
A prewarm runs on the nodes serving the site when it is submitted. A visitor on another node, or whose request has another cache key (port, domain, query), still causes one origin request.
Does it prevent cache poisoning?
Only GET and HEAD requests a cache rule covers are stored, and responses to requests with Authorization or with Set-Cookie are never cached. Do not let the origin vary content by request headers outside the cache key; when you must, add that header to the cache rule.