[Cache] Document CDN-Cache-Control as a BYPASS cause - #32569
Conversation
Review
👉 Fix in your agent 👈Fix the following review findings in PR #32569 (https://github.com/cloudflare/cloudflare-docs/pull/32569).
Before making changes, review each finding and present a brief summary table:
- For each finding, state whether you agree, disagree, or need clarification
- If you disagree (e.g. the fix requires disproportionate effort for minimal benefit,
or the finding is factually incorrect), explain why
- If you need clarification before deciding, ask those questions
- Then share your plan for which issues to tackle and in what order
After triaging, follow this order:
1. Post a comment on this PR for any findings you are skipping, with the finding ID and your reasoning.
2. Then commit the fixes for the legitimate findings.
The comment must come before the commit — the bot reads PR comments when a new
push triggers a review, so skip comments posted after the push will be missed.
---
## Code Review
### Warnings (1)
#### CR-d79577e2bb37 · Incomplete Authorization caveat for Cloudflare-CDN-Cache-Control
- **File:** `src/content/docs/cache/troubleshooting/investigating-uncached-responses.mdx` line 44
- **Issue:** The new bullet says `no-cache`, `max-age=0`, or `s-maxage=0` in `Cloudflare-CDN-Cache-Control` or `CDN-Cache-Control` ‘do not produce `BYPASS`’. However, the existing Origin Cache Control docs state that when `Cloudflare-Cdn-Cache-Control` is set, OCC is forced on and the Authorization logic allows caching only if `s-maxage`, `must-revalidate`, or `public` is also present. So a request that includes an `Authorization` header and `Cloudflare-CDN-Cache-Control: no-cache` or `max-age=0` would still return `BYPASS`, contradicting the unqualified claim.
- **Fix:** Qualify the statement so it does not contradict the Authorization interaction — for example, add ‘unless the request includes an `Authorization` header’ or cross-reference the existing Authorization bullet.
Code ReviewThis code review is in beta and may not always be helpful — use your judgment. Warnings (1)
ConventionsNo convention issues found. Style Guide ReviewNo style-guide issues found. CommandsOnly codeowners can run commands. Post a comment with the command to trigger it.
|
|
This pull request requires reviews from CODEOWNERS as it changes files that match the following patterns:
|
| Common reasons the origin response is treated as not cacheable include: | ||
|
|
||
| * The response exceeds the [maximum cacheable file size](/cache/concepts/default-cache-behavior/#cacheable-size-limits) for your plan. | ||
| * The origin returned a `Cloudflare-CDN-Cache-Control` or `CDN-Cache-Control` header with a non-cacheable directive. Cloudflare evaluates these headers ahead of `Cache-Control`, in the precedence `Cloudflare-CDN-Cache-Control` > `CDN-Cache-Control` > `Cache-Control`. For example, an origin returning both `Cache-Control: public, max-age=3600` and `CDN-Cache-Control: no-store` produces `BYPASS`. Inspect every response header, not just `Cache-Control`. Refer to [CDN-Cache-Control](/cache/concepts/cdn-cache-control/) for the precedence rules. |
There was a problem hiding this comment.
good call, maybe we want to mention Surrogate-Control too.
Cloudflare-CDN-CC > CDN-CC > Surrogate-Control > Cache-Control
cc @zaidoon1
There was a problem hiding this comment.
Hi @mbullock1986 , @zaidoon1
What do you think? Should we mention Surrogate-Control in this page?
|
Both changes LGTM. Left some nits to make the existing change more clear, thanks for the effort @ngayerie |
7ebf475 to
2f583e2
Compare
|
Hi @mbullock1986 @zaidoon1 |
2f583e2 to
ee9f456
Compare
zaidoon1
left a comment
There was a problem hiding this comment.
Checked the CDN-Cache-Control and Age claims against actual behavior. The BYPASS bullet's core point is right, but a few details need tightening. Comments inline.
|
[AI] Thanks @zaidoon1 — all 5 comments applied in
Also reconciled the HIT verification bullet on the same page with your Age scope correction — a fresh local fill from an upper tier can already report a large |
zaidoon1
left a comment
There was a problem hiding this comment.
Latest addresses everything I raised. One clause got lost in the rewrite that I'd put back, plus a couple of small things.
|
[AI] Thanks @zaidoon1 — all 4 comments applied in
|
zaidoon1
left a comment
There was a problem hiding this comment.
Two small ones on the new bullet, neither blocking.
|
[AI] Thanks @zaidoon1 — both applied in
|
6afd6b1 to
f2daf62
Compare
mbullock1986
left a comment
There was a problem hiding this comment.
based on Zaidoon's comments being fixed
|
Hi @zaidoon1 |
- Add a BYPASS bullet documenting Cloudflare-CDN-Cache-Control and CDN-Cache-Control, and their precedence over Cache-Control. An origin returning cacheable Cache-Control alongside a non-cacheable CDN-Cache-Control directive produces BYPASS, and readers otherwise have no signal that these two headers even exist as BYPASS causes. - Rewrite the Age callout and HIT confirmation to describe the Tiered Cache lower-tier fill in plain language, without referring to the internal CacheTieredFill=true field. That field is only visible in the http_requests Logpush dataset, not in HTTP responses, so it is not something readers can inspect.
Address SG-619a15c3d17a from the docs bot review.
Clarify that Age is per-data-center scope: the seconds since the serving data center's local cache admitted or last revalidated the object, rather than the vaguer 'time in Cloudflare's cache'. Applies @foreseaz's suggestion.
cache-responses.mdx:
- Age callout scope: drop 'at that cache' — Age tracks the object's age
in Cloudflare's network-wide cache, not a single data center. A HIT
served locally can carry an Age inherited from an upper tier under
Tiered Cache.
- Age status enumeration: rewrite by cf-cache-status. Age is set on
HIT, STALE, UPDATING. It is absent on MISS, on EXPIRED and REVALIDATED
when the request revalidated against the origin, and on DYNAMIC,
BYPASS, NONE/UNKNOWN. Origin-set Age on uncacheable responses is
proxied to the client — a DYNAMIC or BYPASS response can carry an
Age value that came from the origin, not from Cloudflare.
- CDN-Cache-Control BYPASS bullet:
- Name the directives: only no-store and bare private produce
BYPASS. no-cache, max-age=0, s-maxage=0 do not — they produce
MISS then REVALIDATED or EXPIRED.
- Add the Edge Cache TTL override, same as for Cache-Control:
no-store.
- Drop the Origin Cache Control condition — these headers always
follow OCC-style semantics regardless of the zone setting.
investigating-uncached-responses.mdx:
- Mirror the same CDN-Cache-Control corrections, framed for the
troubleshooting reader: note that Cloudflare does not forward
Cloudflare-CDN-Cache-Control to the client, so a BYPASS without a
visible CDN-Cache-Control header means checking what the origin
actually sent (or dropping the header at origin and retesting).
- HIT verification Age bullet: reconcile with the Age scope correction.
With Tiered Cache, a fresh local fill can already report a large Age
inherited from an upper tier — not 'may be absent'.
cache-responses.mdx: - Age callout: qualify the reset rule as 'revalidation against the origin'. With Tiered Cache, a lower tier revalidating against an upper tier that still has the object picks up the upper tier's age rather than resetting to zero. - CDN-Cache-Control BYPASS bullet: split the sentence on the no-cache/max-age=0/s-maxage=0 clarification per style guide (no semicolons). investigating-uncached-responses.mdx: - CDN-Cache-Control BYPASS bullet: pull the no-cache/max-age=0/ s-maxage=0 clarification into its own bullet. Six-sentence walls are hard to scan while debugging, and the clarification points the reader elsewhere (to Repeated MISS), so it earns a separate bullet. Also removes the semicolon flagged on the reference page. - HIT verify Age bullet: restore the absent-on-fill case. On the request that fills a lower tier from an upper tier, the client gets HIT with no Age at all — the HIT reflects the upper tier, and the local data center has not served it from cache yet. The next request includes Age and can already be large under Tiered Cache.
investigating-uncached-responses.mdx: - Name the headers explicitly at the start of the 'no-cache / max-age=0 / s-maxage=0' bullet, rather than relying on 'these headers'. A scanner reading only the bolded start of BYPASS bullets could mis-read a 'these headers' bullet as a BYPASS cause. - Drop the pointer to 'Repeated MISS'. That section covers cache key variance and eviction, which is not what the MISS then REVALIDATED / EXPIRED pattern indicates. The bullet already states the expected sequence, and 'Confirm the response reaches cache' already covers verification.
f2daf62 to
7642ef2
Compare
Two small follow-ups to #32423.
What
cache-responses.mdxandinvestigating-uncached-responses.mdxdocumentingCloudflare-CDN-Cache-ControlandCDN-Cache-Control, with the precedence chainCloudflare-CDN-Cache-Control>CDN-Cache-Control>Cache-Control. Uses a concrete example so the reader sees that a cacheableCache-Controlalongside a non-cacheableCDN-Cache-Controlstill producesBYPASS.Agecallout incache-responses.mdxand the corresponding HIT-verification bullet in the troubleshooting page. Both currently mentionCacheTieredFill=true, which is anhttp_requestsLogpush field, not an HTTP header — readers cannot observe it on a response.Why
Neither BYPASS list mentioned
Cloudflare-CDN-Cache-ControlorCDN-Cache-Control. When bothCache-ControlandCDN-Cache-Controlare set,CDN-Cache-Controlwins per CDN-Cache-Control, so a reader debugging aBYPASSwhile only looking atCache-Controlhas no signal from these pages that another header is in play.@zaidoon1 for review.