[{"data":1,"prerenderedAt":1046},["ShallowReactive",2],{"content:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers":3,"surroundings:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers":1037},{"id":4,"title":5,"body":6,"description":1018,"extension":1019,"meta":1020,"navigation":1031,"path":1032,"seo":1033,"stem":1035,"__hash__":1036},"content\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers\u002Findex.md","Diagnosing CDN Cache Misses from Response Headers",{"type":7,"value":8,"toc":1002},"minimark",[9,14,34,53,239,244,328,332,343,352,358,364,492,496,501,613,619,623,639,643,653,657,667,754,758,773,777,795,799,825,829,835,844,856,862,866,878,893,908,924,933,942,951,960,964,987,992,995,998],[10,11,13],"h1",{"id":12},"how-to-diagnose-cdn-cache-misses-from-response-headers","How to Diagnose CDN Cache Misses from Response Headers",[15,16,17,18,23,24,28,29,33],"p",{},"This guide gives ",[19,20,22],"a",{"href":21},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002F","CDN Edge Caching Configuration"," a debugging method, within ",[19,25,27],{"href":26},"\u002Fadvanced-caching-strategies-cdn-architecture\u002F","Advanced Caching Strategies & CDN Architecture",". When TTFB is slow and you suspect the CDN is not caching, the answer is almost always in the response headers. CDNs report cache outcomes (hit, miss, expired, bypass, dynamic), and the origin's caching headers, cookies and ",[30,31,32],"code",{},"Vary"," explain why. Reading them systematically turns \"the cache isn't working\" into a specific cause in a few minutes.",[15,35,36,37,40,41,44,45,48,49,52],{},"The vocabulary differs by vendor — ",[30,38,39],{},"cf-cache-status"," at Cloudflare, ",[30,42,43],{},"x-cache"," at CloudFront and Fastly, ",[30,46,47],{},"x-cache-status"," or ",[30,50,51],{},"Akamai-Cache-Status"," elsewhere — but the questions are the same: Was the response eligible for caching? Was it in the cache? If it was, was it fresh? And if it was not eligible, which header or rule prevented it?",[15,54,55],{},[56,57,63,64,63,71,63,75,63,78,63,96,63,104,63,110,63,117,63,124,63,129,63,135,63,139,63,148,63,154,63,158,63,164,63,168,63,172,63,176,63,178,63,182,63,186,63,189,63,192,63,196,63,199,63,203,63,207,63,209,63,212,63,215,63,218,63,222,63,225,63,231,63,235,63],"svg",{"viewBox":58,"width":59,"role":60,"ariaLabel":61,"style":62},"0 0 760 373","100%","img","Decision sequence for diagnosing why a CDN response was not a cache hit using response headers.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[65,66],"rect",{"className":67,"x":69,"y":69,"width":59,"height":59,"fill":70},[68],"svg-canvas","0","#ffffff",[72,73,74],"title",{},"Reading a cache miss",[76,77,61],"desc",{},[79,80,81],"defs",{},[82,83,90],"marker",{"id":84,"viewBox":85,"refX":86,"refY":87,"markerWidth":88,"markerHeight":88,"orient":89},"fad0f6b52e","0 0 10 10","9","5","7","auto-start-reverse",[91,92],"path",{"d":93,"fill":94,"style":95},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[65,97],{"x":98,"y":98,"width":99,"height":100,"rx":101,"fill":102,"stroke":94,"style":103},"1","758","371","10","none","stroke-opacity:0.18",[105,106,74],"text",{"x":107,"y":108,"fill":94,"style":109},"28.0","34.0","font-size:16px;font-weight:700",[65,111],{"x":107,"y":112,"width":113,"height":114,"rx":115,"fill":94,"stroke":94,"style":116},"56.0","320.0","50.0","6","fill-opacity:0.06;stroke-opacity:0.4",[105,118,123],{"x":119,"y":120,"fill":94,"style":121,"textAnchor":122},"188.0","85.5","font-size:13px;font-weight:700","middle","Status says BYPASS or DYNAMIC?",[65,125],{"x":126,"y":112,"width":113,"height":114,"rx":115,"fill":127,"stroke":127,"style":128},"412.0","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[105,130,134],{"x":131,"y":132,"fill":94,"style":133,"textAnchor":122},"572.0","77.5","font-size:12.5px","Not eligible — check Cache-Control, Set-Cookie",[105,136,138],{"x":131,"y":137,"fill":94,"style":133,"textAnchor":122},"93.5","and CDN rules",[140,141],"line",{"x1":142,"y1":143,"x2":144,"y2":143,"stroke":94,"strokeWidth":145,"style":146,"markerEnd":147},"348.0","81.0","410.0","1.5","stroke-opacity:0.6","url(#fad0f6b52e)",[105,149,153],{"x":150,"y":151,"fill":127,"style":152,"textAnchor":122},"380.0","74.0","font-size:11.5px;font-weight:700","yes",[140,155],{"x1":119,"y1":156,"x2":119,"y2":157,"stroke":94,"strokeWidth":145,"style":146,"markerEnd":147},"106.0","140.0",[105,159,163],{"x":160,"y":161,"fill":162,"style":152},"196.0","128.0","#51617a","no",[65,165],{"x":107,"y":166,"width":113,"height":167,"rx":115,"fill":94,"stroke":94,"style":116},"142.0","52.0",[105,169,171],{"x":119,"y":170,"fill":94,"style":121,"textAnchor":122},"164.0","Status says MISS repeatedly for the same",[105,173,175],{"x":119,"y":174,"fill":94,"style":121,"textAnchor":122},"181.0","URL?",[65,177],{"x":126,"y":166,"width":113,"height":167,"rx":115,"fill":127,"stroke":127,"style":128},[105,179,181],{"x":131,"y":180,"fill":94,"style":133,"textAnchor":122},"164.5","Key fragmentation or Vary — compare cache",[105,183,185],{"x":131,"y":184,"fill":94,"style":133,"textAnchor":122},"180.5","keys",[140,187],{"x1":142,"y1":188,"x2":144,"y2":188,"stroke":94,"strokeWidth":145,"style":146,"markerEnd":147},"168.0",[105,190,153],{"x":150,"y":191,"fill":127,"style":152,"textAnchor":122},"161.0",[140,193],{"x1":119,"y1":194,"x2":119,"y2":195,"stroke":94,"strokeWidth":145,"style":146,"markerEnd":147},"194.0","228.0",[105,197,163],{"x":160,"y":198,"fill":162,"style":152},"216.0",[65,200],{"x":107,"y":201,"width":113,"height":202,"rx":115,"fill":94,"stroke":94,"style":116},"230.0","35.0",[105,204,206],{"x":119,"y":205,"fill":94,"style":121,"textAnchor":122},"252.0","Status says EXPIRED \u002F REVALIDATED?",[65,208],{"x":126,"y":201,"width":113,"height":202,"rx":115,"fill":127,"stroke":127,"style":128},[105,210,211],{"x":131,"y":205,"fill":94,"style":133,"textAnchor":122},"TTL too short — check s-maxage and Age",[140,213],{"x1":142,"y1":214,"x2":144,"y2":214,"stroke":94,"strokeWidth":145,"style":146,"markerEnd":147},"247.5",[105,216,153],{"x":150,"y":217,"fill":127,"style":152,"textAnchor":122},"240.5",[140,219],{"x1":119,"y1":220,"x2":119,"y2":221,"stroke":94,"strokeWidth":145,"style":146,"markerEnd":147},"265.0","299.0",[105,223,163],{"x":160,"y":224,"fill":162,"style":152},"287.0",[65,226],{"x":107,"y":227,"width":113,"height":114,"rx":115,"fill":228,"stroke":229,"style":230},"301.0","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[105,232,234],{"x":119,"y":233,"fill":94,"style":133,"textAnchor":122},"322.5","HIT — look elsewhere (origin of the slowness is",[105,236,238],{"x":119,"y":237,"fill":94,"style":133,"textAnchor":122},"338.5","not the cache)",[240,241,243],"h2",{"id":242},"rapid-diagnosis","Rapid Diagnosis",[245,246,247,259,276,302,311],"ul",{},[248,249,250,254,255,258],"li",{},[251,252,253],"strong",{},"Request the same URL twice"," with ",[30,256,257],{},"curl -sI"," and compare cache status. A second MISS is the most informative signal.",[248,260,261,268,269,271,272,275],{},[251,262,263,264,267],{},"Read ",[30,265,266],{},"Age","."," On a hit, ",[30,270,266],{}," shows how long the object has been cached; ",[30,273,274],{},"Age: 0"," on every request means it is never reused.",[248,277,278,63,283,286,287,286,290,293,294,297,298,301],{},[251,279,263,280,267],{},[30,281,282],{},"Cache-Control",[30,284,285],{},"private",", ",[30,288,289],{},"no-store",[30,291,292],{},"no-cache"," or a missing ",[30,295,296],{},"s-maxage","\u002F",[30,299,300],{},"max-age"," usually explain BYPASS or DYNAMIC.",[248,303,304,310],{},[251,305,306,307,267],{},"Look for ",[30,308,309],{},"Set-Cookie"," Many CDNs will not cache responses that set cookies.",[248,312,313,317,318,286,321,48,324,327],{},[251,314,263,315,267],{},[30,316,32],{}," Values like ",[30,319,320],{},"Cookie",[30,322,323],{},"User-Agent",[30,325,326],{},"Accept-Language"," fragment the cache.",[240,329,331],{"id":330},"root-cause-analysis","Root Cause Analysis",[15,333,334,337,338,286,340,342],{},[251,335,336],{},"1. Ineligible by headers."," The origin forbids shared caching (",[30,339,285],{},[30,341,289],{},") or gives no TTL, and the CDN's default for that content type is not to cache.",[15,344,345,348,349,267],{},[251,346,347],{},"2. Ineligible by rules."," CDN configuration bypasses certain paths, methods (POST), or requests with cookies or ",[30,350,351],{},"Authorization",[15,353,354,357],{},[251,355,356],{},"3. Eligible but not found."," The key differs each time (query parameters, Vary) or the object was evicted or purged.",[15,359,360,363],{},[251,361,362],{},"4. Found but stale."," The TTL expired; the CDN revalidated or refetched from origin.",[15,365,366],{},[56,367,63,370,63,373,63,376,63,378,63,381,63,383,63,386,63,393,63,397,63,401,63,404,63,408,63,412,63,416,63,418,63,421,63,423,63,426,63,429,63,433,63,435,63,437,63,439,63,442,63,445,63,449,63,451,63,454,63,456,63,459,63,462,63,466,63,468,63,471,63,473,63,476,63,479,63,483,63,485,63,487,63,489,63],{"viewBox":368,"width":59,"role":60,"ariaLabel":369,"style":62},"0 0 760 258","How major CDNs report cache outcomes in response headers.",[65,371],{"className":372,"x":69,"y":69,"width":59,"height":59,"fill":70},[68],[72,374,375],{},"Cache status headers by vendor",[76,377,369],{},[65,379],{"x":98,"y":98,"width":99,"height":380,"rx":101,"fill":102,"stroke":94,"style":103},"256",[105,382,375],{"x":107,"y":108,"fill":94,"style":109},[65,384],{"x":107,"y":112,"width":120,"height":385,"rx":69,"fill":94,"stroke":94,"style":116},"30.0",[105,387,392],{"x":388,"y":389,"fill":94,"style":390,"textAnchor":391},"38.0","75.5","font-size:12.5px;font-weight:700","start","CDN",[65,394],{"x":395,"y":112,"width":396,"height":385,"rx":69,"fill":94,"stroke":94,"style":116},"113.5","309.2",[105,398,400],{"x":399,"y":389,"fill":94,"style":390,"textAnchor":122},"268.1","Header",[65,402],{"x":403,"y":112,"width":396,"height":385,"rx":69,"fill":94,"stroke":94,"style":116},"422.8",[105,405,407],{"x":406,"y":389,"fill":94,"style":390,"textAnchor":122},"577.4","Common values",[65,409],{"x":107,"y":410,"width":120,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},"86.0","stroke-opacity:0.35",[105,413,415],{"x":388,"y":414,"fill":94,"style":390,"textAnchor":391},"105.5","Cloudflare",[65,417],{"x":395,"y":410,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,419,39],{"x":399,"y":414,"fill":94,"style":420,"textAnchor":122},"font-size:12px",[65,422],{"x":403,"y":410,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,424,425],{"x":406,"y":414,"fill":94,"style":420,"textAnchor":122},"HIT, MISS, EXPIRED, BYPASS, DYNAMIC",[65,427],{"x":107,"y":428,"width":120,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},"116.0",[105,430,432],{"x":388,"y":431,"fill":94,"style":390,"textAnchor":391},"135.5","CloudFront",[65,434],{"x":395,"y":428,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,436,43],{"x":399,"y":431,"fill":94,"style":420,"textAnchor":122},[65,438],{"x":403,"y":428,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,440,441],{"x":406,"y":431,"fill":94,"style":420,"textAnchor":122},"Hit from cloudfront, Miss from cloudfront",[65,443],{"x":107,"y":444,"width":120,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},"146.0",[105,446,448],{"x":388,"y":447,"fill":94,"style":390,"textAnchor":391},"165.5","Fastly",[65,450],{"x":395,"y":444,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,452,453],{"x":399,"y":447,"fill":94,"style":420,"textAnchor":122},"x-cache (+ x-cache-hits)",[65,455],{"x":403,"y":444,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,457,458],{"x":406,"y":447,"fill":94,"style":420,"textAnchor":122},"HIT, MISS (per tier)",[65,460],{"x":107,"y":461,"width":120,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},"176.0",[105,463,465],{"x":388,"y":464,"fill":94,"style":390,"textAnchor":391},"195.5","Akamai",[65,467],{"x":395,"y":461,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,469,470],{"x":399,"y":464,"fill":94,"style":420,"textAnchor":122},"x-cache (debug headers)",[65,472],{"x":403,"y":461,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,474,475],{"x":406,"y":464,"fill":94,"style":420,"textAnchor":122},"TCP_HIT, TCP_MISS",[65,477],{"x":107,"y":478,"width":120,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},"206.0",[105,480,482],{"x":388,"y":481,"fill":94,"style":390,"textAnchor":391},"225.5","Any",[65,484],{"x":395,"y":478,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,486,266],{"x":399,"y":481,"fill":94,"style":420,"textAnchor":122},[65,488],{"x":403,"y":478,"width":396,"height":385,"rx":69,"fill":102,"stroke":94,"style":411},[105,490,491],{"x":406,"y":481,"fill":94,"style":420,"textAnchor":122},"seconds in cache",[240,493,495],{"id":494},"step-by-step-resolution","Step-by-Step Resolution",[497,498,500],"h3",{"id":499},"_1-capture-headers-for-repeated-requests","1. Capture headers for repeated requests",[502,503,508],"pre",{"className":504,"code":505,"language":506,"meta":507,"style":507},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","for i in 1 2 3; do\n  curl -s -o \u002Fdev\u002Fnull -D - 'https:\u002F\u002Fwww.example.com\u002Fproducts\u002F42' \\\n    | grep -iE '^(cf-cache-status|x-cache|age|cache-control|vary|set-cookie|cdn-cache-control):'\n  echo ---\ndone\n# trade-off: curl sends no cookies by default. Repeat with the cookies a real\n# browser sends (copy as cURL from DevTools), because cookies often cause bypass.\n","bash","",[30,509,510,541,570,585,594,600,607],{"__ignoreMap":507},[511,512,514,518,522,525,529,532,535,538],"span",{"class":140,"line":513},1,[511,515,517],{"class":516},"sPARh","for",[511,519,521],{"class":520},"saISM"," i ",[511,523,524],{"class":516},"in",[511,526,528],{"class":527},"sZ8jY"," 1",[511,530,531],{"class":527}," 2",[511,533,534],{"class":527}," 3",[511,536,537],{"class":520},"; ",[511,539,540],{"class":516},"do\n",[511,542,544,548,552,555,558,561,564,567],{"class":140,"line":543},2,[511,545,547],{"class":546},"sQw3B","  curl",[511,549,551],{"class":550},"sPXB4"," -s",[511,553,554],{"class":550}," -o",[511,556,557],{"class":527}," \u002Fdev\u002Fnull",[511,559,560],{"class":550}," -D",[511,562,563],{"class":527}," -",[511,565,566],{"class":527}," 'https:\u002F\u002Fwww.example.com\u002Fproducts\u002F42'",[511,568,569],{"class":516}," \\\n",[511,571,573,576,579,582],{"class":140,"line":572},3,[511,574,575],{"class":516},"    |",[511,577,578],{"class":546}," grep",[511,580,581],{"class":550}," -iE",[511,583,584],{"class":527}," '^(cf-cache-status|x-cache|age|cache-control|vary|set-cookie|cdn-cache-control):'\n",[511,586,588,591],{"class":140,"line":587},4,[511,589,590],{"class":550},"  echo",[511,592,593],{"class":550}," ---\n",[511,595,597],{"class":140,"line":596},5,[511,598,599],{"class":516},"done\n",[511,601,603],{"class":140,"line":602},6,[511,604,606],{"class":605},"sjfSM","# trade-off: curl sends no cookies by default. Repeat with the cookies a real\n",[511,608,610],{"class":140,"line":609},7,[511,611,612],{"class":605},"# browser sends (copy as cURL from DevTools), because cookies often cause bypass.\n",[15,614,615,616,618],{},"Expected outcome: a clear pattern — hits with growing ",[30,617,266],{},", or misses with a visible cause.",[497,620,622],{"id":621},"_2-fix-eligibility-first","2. Fix eligibility first",[15,624,625,626,628,629,297,632,635,636,638],{},"If the status is BYPASS\u002FDYNAMIC: add explicit shared-cache headers (",[30,627,296],{}," or a CDN-specific header such as ",[30,630,631],{},"CDN-Cache-Control",[30,633,634],{},"Surrogate-Control","), remove ",[30,637,309],{}," from cacheable responses, and check CDN rules for path or cookie bypasses.",[497,640,642],{"id":641},"_3-fix-key-fragmentation","3. Fix key fragmentation",[15,644,645,646,648,649,267],{},"If repeated requests for \"the same\" URL miss, compare the exact URLs and request headers involved. Tracking parameters and ",[30,647,32],{}," are the usual causes — see ",[19,650,652],{"href":651},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fnormalizing-cache-keys-to-raise-hit-rate\u002F","normalizing cache keys to raise hit rate",[497,654,656],{"id":655},"_4-fix-freshness","4. Fix freshness",[15,658,659,660,662,663,666],{},"If responses expire too quickly, lengthen ",[30,661,296],{}," and add ",[30,664,665],{},"stale-while-revalidate",", relying on purges for correctness rather than short TTLs.",[15,668,669],{},[56,670,63,673,63,676,63,679,63,681,63,684,63,686,63,693,63,700,63,705,63,709,63,714,63,718,63,722,63,726,63,730,63,734,63,738,63,742,63,745,63,750,63],{"viewBox":671,"width":59,"role":60,"ariaLabel":672,"style":62},"0 0 760 225","Bar chart of the causes of HTML cache misses found by reading response headers across a site's top templates.",[65,674],{"className":675,"x":69,"y":69,"width":59,"height":59,"fill":70},[68],[72,677,678],{},"Causes of HTML misses found in one audit",[76,680,672],{},[65,682],{"x":98,"y":98,"width":99,"height":683,"rx":101,"fill":102,"stroke":94,"style":103},"223",[105,685,678],{"x":107,"y":108,"fill":94,"style":109},[105,687,692],{"x":688,"y":689,"fill":94,"style":690,"textAnchor":691},"164.6","70.0","font-size:13px","end","Set-Cookie on HTML",[65,694],{"x":695,"y":112,"width":696,"height":697,"rx":698,"fill":228,"stroke":229,"style":699},"176.6","491.4","19","3","fill-opacity:0.7;stroke-opacity:0.9",[105,701,704],{"x":702,"y":689,"fill":94,"style":703},"674.0","font-size:12px;font-weight:600","38%",[105,706,708],{"x":688,"y":707,"fill":94,"style":690,"textAnchor":691},"101.0","Tracking params in key",[65,710],{"x":695,"y":711,"width":712,"height":697,"rx":698,"fill":127,"stroke":127,"style":713},"87.0","349.2","fill-opacity:0.55;stroke-opacity:0.9",[105,715,717],{"x":716,"y":707,"fill":94,"style":703},"531.8","27%",[105,719,721],{"x":688,"y":720,"fill":94,"style":690,"textAnchor":691},"132.0","Cache-Control: private",[65,723],{"x":695,"y":724,"width":725,"height":697,"rx":698,"fill":127,"stroke":127,"style":713},"118.0","245.7",[105,727,729],{"x":728,"y":720,"fill":94,"style":703},"428.3","19%",[105,731,733],{"x":688,"y":732,"fill":94,"style":690,"textAnchor":691},"163.0","TTL expired (60s)",[65,735],{"x":695,"y":736,"width":737,"height":697,"rx":698,"fill":127,"stroke":127,"style":713},"149.0","142.2",[105,739,741],{"x":740,"y":732,"fill":94,"style":703},"324.8","11%",[105,743,744],{"x":688,"y":194,"fill":94,"style":690,"textAnchor":691},"Other",[65,746],{"x":695,"y":747,"width":748,"height":697,"rx":698,"fill":94,"stroke":94,"style":749},"180.0","64.7","fill-opacity:0.7;stroke-opacity:0.4",[105,751,753],{"x":752,"y":194,"fill":94,"style":703},"247.3","5%",[240,755,757],{"id":756},"verification","Verification",[15,759,760,761,763,764,767,768,772],{},"After each fix, repeat the curl loop: the second and later requests should be hits with increasing ",[30,762,266],{},". Add the cache status to ",[30,765,766],{},"Server-Timing"," so RUM can chart hit ratio as experienced by real users (as described in ",[19,769,771],{"href":770},"\u002Fcore-web-vitals-measurement\u002Frum-beacons-and-field-data-collection\u002Fexposing-backend-timing-with-server-timing-headers\u002F","exposing backend timing with Server-Timing headers","), and track TTFB p75 split by status.",[240,774,776],{"id":775},"worked-example-the-session-cookie-on-every-page","Worked Example: The Session Cookie on Every Page",[15,778,779,780,783,784,787,788,791,792,794],{},"A content site's HTML hit ratio was 12% despite ",[30,781,782],{},"Cache-Control: public, s-maxage=600",". Headers showed ",[30,785,786],{},"cf-cache-status: DYNAMIC"," and a ",[30,789,790],{},"Set-Cookie: session=…"," on every response — the framework refreshed an anonymous session on every page view. Moving session creation to the first interaction that needed it (comment posting) removed the header from page responses; the next curl loop showed MISS then HIT with growing ",[30,793,266],{},". The hit ratio rose to 88% and TTFB p75 dropped from 520ms to 95ms.",[240,796,798],{"id":797},"common-mistakes","Common Mistakes",[245,800,801,807,813,819],{},[248,802,803,806],{},[251,804,805],{},"Testing only without cookies."," Real browsers send cookies that can trigger bypass rules.",[248,808,809,812],{},[251,810,811],{},"Trusting the CDN dashboard average."," Aggregates hide per-template problems; inspect headers per template.",[248,814,815,818],{},[251,816,817],{},"Confusing browser cache with CDN cache."," DevTools \"from disk cache\" says nothing about the CDN; use the CDN's status header.",[248,820,821,824],{},[251,822,823],{},"Debugging through a single PoP."," Results differ by location; test from the regions your users are in.",[240,826,828],{"id":827},"edge-cases","Edge Cases",[15,830,831,834],{},[251,832,833],{},"Multiple cache layers."," A response can be a CDN hit but an origin-proxy miss, or vice versa; each layer may add its own status header. Read them all.",[15,836,837,840,841,843],{},[251,838,839],{},"Tiered caches."," Some CDNs report hits from the parent tier differently (for example, Fastly's per-tier ",[30,842,43],{}," values); a \"MISS, HIT\" pair means the edge missed and the shield hit.",[15,845,846,63,849,48,852,855],{},[251,847,848],{},"Revalidated responses.",[30,850,851],{},"REVALIDATED",[30,853,854],{},"304"," interactions with the origin are cheaper than full misses but still pay origin latency.",[15,857,858,861],{},[251,859,860],{},"Debug headers."," Many CDNs offer extra debug headers on request (Akamai Pragma headers, Fastly debug); enable them in staging for detailed reasons.",[240,863,865],{"id":864},"faq","FAQ",[867,868,871,875],"details",{"className":869},[870],"faq-item",[872,873,874],"summary",{},"What does DYNAMIC mean on Cloudflare?",[15,876,877],{},"The response was not eligible for caching under the current rules — typically HTML or JSON without a rule to cache it, or a response with cache-preventing headers. It is not a miss; it was never going to be cached.",[867,879,881,884],{"className":880},[870],[872,882,883],{},"Why is Age missing on hits?",[15,885,886,887,889,890,892],{},"Some CDNs omit ",[30,888,266],{}," when it is zero or when serving from certain tiers. Use the status header as the primary signal and ",[30,891,266],{}," as a secondary one.",[867,894,896,899],{"className":895},[870],[872,897,898],{},"Should Cache-Control for browsers and CDNs differ?",[15,900,901,902,904,905,907],{},"Often, yes. Use ",[30,903,296],{}," (or a CDN-specific header) to give the CDN a long TTL you can purge, and a short or zero ",[30,906,300],{}," for browsers, which you cannot purge.",[867,909,911,914],{"className":910},[870],[872,912,913],{},"How do I see cache status in real users' sessions?",[15,915,916,917,919,920,923],{},"Expose it via ",[30,918,766],{}," (for example ",[30,921,922],{},"cdn-cache;desc=HIT","), which the browser makes available to JavaScript through Resource and Navigation Timing, then include it in your RUM beacon.",[867,925,927,930],{"className":926},[870],[872,928,929],{},"Can a CDN cache responses to requests with cookies?",[15,931,932],{},"Yes, if configured to; whether it should depends on whether the response varies by cookie. For shared content, configure the CDN to ignore cookies for those paths and make sure the origin does too.",[867,934,936,939],{"className":935},[870],[872,937,938],{},"Can a response be a hit but still slow?",[15,940,941],{},"Yes. A hit removes origin latency, but transfer of a large response, slow TLS setup, or an edge function doing work after the cache lookup can still make TTFB high. If the status is HIT and TTFB is poor, look at connection timing and edge processing instead of caching.",[867,943,945,948],{"className":944},[870],[872,946,947],{},"Which headers should I log at the edge for later analysis?",[15,949,950],{},"Cache status, Age, the computed cache key (or a hash of it), response Cache-Control, whether Set-Cookie was present, and the PoP or region. With those in access logs, most miss investigations can be done with a query rather than by reproducing requests manually.",[867,952,954,957],{"className":953},[870],[872,955,956],{},"What is the fastest way to check many URLs?",[15,958,959],{},"Script the curl loop over a list of representative URLs per template, run it twice, and tabulate status, Age, Cache-Control, Vary and Set-Cookie for the second pass. A spreadsheet of fifty URLs usually reveals the dominant cause in minutes, and the script doubles as a regression check after configuration changes.",[240,961,963],{"id":962},"related","Related",[245,965,966,973,980],{},[248,967,968,972],{},[19,969,971],{"href":970},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fvary-header-pitfalls-that-destroy-cdn-hit-rate\u002F","Vary header pitfalls that destroy CDN hit rate"," — one of the main causes of repeated misses.",[248,974,975,979],{},[19,976,978],{"href":977},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fhttp-cache-control-headers-explained\u002Fcache-control-for-html-documents\u002F","Cache-Control for HTML documents"," — choosing headers that make HTML cacheable.",[248,981,982,986],{},[19,983,985],{"href":984},"\u002Fnetwork-protocol-optimization\u002Ftime-to-first-byte-optimization\u002Fdiagnosing-slow-ttfb-with-server-timing\u002F","Diagnosing slow TTFB with Server-Timing"," — when the cache is fine and the origin is slow.",[988,989,991],"script",{"type":990},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Diagnose CDN Cache Misses from Response Headers\",\n  \"description\": \"A header-by-header method for working out why a response was not served from the CDN cache, across the major CDN vendors.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Capture headers for repeated requests\",\n      \"text\": \"Expected outcome: a clear pattern — hits with growing Age, or misses with a visible cause.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Fix eligibility first\",\n      \"text\": \"If the status is BYPASS\u002FDYNAMIC: add explicit shared-cache headers (s-maxage or a CDN-specific header such as CDN-Cache-Control\u002FSurrogate-Control), remove Set-Cookie from cacheable responses, and check CDN rules for path or cookie bypasses.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Fix key fragmentation\",\n      \"text\": \"If repeated requests for \\\"the same\\\" URL miss, compare the exact URLs and request headers involved.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Fix freshness\",\n      \"text\": \"If responses expire too quickly, lengthen s-maxage and add stale-while-revalidate, relying on purges for correctness rather than short TTLs.\"\n    }\n  ]\n}\n",[988,993,994],{"type":990},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Diagnose CDN Cache Misses from Response Headers\",\n  \"description\": \"A header-by-header method for working out why a response was not served from the CDN cache, across the major CDN vendors.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers\u002F\"\n  }\n}\n",[988,996,997],{"type":990},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Advanced Caching Strategies & CDN Architecture\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"CDN Edge Caching Configuration\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Diagnosing CDN Cache Misses from Response Headers\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers\u002F\"\n    }\n  ]\n}\n",[999,1000,1001],"style",{},"html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}",{"title":507,"searchDepth":543,"depth":543,"links":1003},[1004,1005,1006,1012,1013,1014,1015,1016,1017],{"id":242,"depth":543,"text":243},{"id":330,"depth":543,"text":331},{"id":494,"depth":543,"text":495,"children":1007},[1008,1009,1010,1011],{"id":499,"depth":572,"text":500},{"id":621,"depth":572,"text":622},{"id":641,"depth":572,"text":642},{"id":655,"depth":572,"text":656},{"id":756,"depth":543,"text":757},{"id":775,"depth":543,"text":776},{"id":797,"depth":543,"text":798},{"id":827,"depth":543,"text":828},{"id":864,"depth":543,"text":865},{"id":962,"depth":543,"text":963},"A header-by-header method for working out why a response was not served from the CDN cache, across the major CDN vendors.","md",{"slug":1021,"type":1022,"breadcrumb":1023,"datePublished":1030,"dateModified":1030},"diagnosing-cdn-cache-misses-from-response-headers","article",[1024,1026,1027,1028],{"name":1025,"url":297},"Home",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1029},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers\u002F","2026-10-06",true,"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers",{"title":5,"description":1034},"Read cf-cache-status, x-cache, Age, Via and Cache-Control to find out why a CDN missed, bypassed or expired a response, and fix the cause instead of guessing.","advanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fdiagnosing-cdn-cache-misses-from-response-headers\u002Findex","O0y6Tt3cN2UDeWVL5StKIJ23c1VLgjJrbRr1jdbefVk",[1038,1042],{"title":1039,"path":1040,"stem":1041,"children":-1},"Configuring stale-if-error for origin outages","\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fconfiguring-stale-if-error-for-origin-outages","advanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fconfiguring-stale-if-error-for-origin-outages\u002Findex",{"title":1043,"path":1044,"stem":1045,"children":-1},"Normalizing Cache Keys to Raise Hit Rate","\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fnormalizing-cache-keys-to-raise-hit-rate","advanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fnormalizing-cache-keys-to-raise-hit-rate\u002Findex",1791308075112]