[{"data":1,"prerenderedAt":1096},["ShallowReactive",2],{"content:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache":3,"surroundings:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache":1088},{"id":4,"title":5,"body":6,"description":1068,"extension":1069,"meta":1070,"navigation":1082,"path":1083,"seo":1084,"stem":1086,"__hash__":1087},"content\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002Findex.md","Cache-Control no-store and bfcache",{"type":7,"value":8,"toc":1051},"minimark",[9,14,38,58,223,228,266,270,279,290,301,310,449,453,458,464,468,581,584,588,595,734,737,741,749,812,816,826,830,845,849,886,890,898,907,916,925,929,944,948,960,974,983,997,1009,1013,1036,1041,1044,1047],[10,11,13],"h1",{"id":12},"cache-control-no-store-and-the-backforward-cache","Cache-Control no-store and the Back\u002FForward Cache",[15,16,17,18,23,24,28,29,33,34,37],"p",{},"This guide resolves a common conflict within ",[19,20,22],"a",{"href":21},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002F","Back\u002FForward Cache (bfcache)",", part of ",[19,25,27],{"href":26},"\u002Fadvanced-caching-strategies-cdn-architecture\u002F","Advanced Caching Strategies & CDN Architecture",". Many applications send ",[30,31,32],"code",{},"Cache-Control: no-store"," on every HTML response — sometimes deliberately for security, often because a framework, middleware or CDN rule sets it globally \"to be safe\". Browsers have historically treated ",[30,35,36],{},"no-store"," documents as ineligible for bfcache, so every back navigation to those pages becomes a full reload.",[15,39,40,41,43,44,46,47,50,51,54,55,57],{},"The fix is not to remove ",[30,42,36],{}," everywhere. It is to understand what ",[30,45,36],{}," actually protects against, apply it only where that protection matters, and use ",[30,48,49],{},"no-cache"," (revalidate before reuse) or ",[30,52,53],{},"private"," (do not store in shared caches) where the real goal is freshness or keeping data out of CDNs. Chromium has also been experimenting with allowing some ",[30,56,36],{}," pages into bfcache under strict conditions, but that behaviour is not something to design around.",[15,59,60],{},[61,62,68,69,68,76,68,80,68,83,68,92,68,98,68,104,68,111,68,115,68,120,68,123,68,127,68,130,68,134,68,138,68,141,68,146,68,150,68,152,68,155,68,157,68,160,68,163,68,166,68,170,68,173,68,175,68,178,68,180,68,183,68,186,68,189,68,191,68,194,68,196,68,199,68,201,68,203,68,206,68,210,68,212,68,214,68,216,68,219,68,221,68],"svg",{"viewBox":63,"width":64,"role":65,"ariaLabel":66,"style":67},"0 0 760 228","100%","img","Comparison of no-store, no-cache, private and max-age=0 by storage, revalidation and bfcache effect.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[70,71],"rect",{"className":72,"x":74,"y":74,"width":64,"height":64,"fill":75},[73],"svg-canvas","0","#ffffff",[77,78,79],"title",{},"What each Cache-Control directive actually does",[81,82,66],"desc",{},[70,84],{"x":85,"y":85,"width":86,"height":87,"rx":88,"fill":89,"stroke":90,"style":91},"1","758","226","10","none","currentColor","stroke-opacity:0.18",[93,94,79],"text",{"x":95,"y":96,"fill":90,"style":97},"28.0","34.0","font-size:16px;font-weight:700",[70,99],{"x":95,"y":100,"width":101,"height":102,"rx":74,"fill":90,"stroke":90,"style":103},"56.0","85.3","30.0","fill-opacity:0.06;stroke-opacity:0.4",[93,105,110],{"x":106,"y":107,"fill":90,"style":108,"textAnchor":109},"38.0","75.5","font-size:12.5px;font-weight:700","start","Directive",[70,112],{"x":113,"y":100,"width":114,"height":102,"rx":74,"fill":90,"stroke":90,"style":103},"113.3","206.2",[93,116,119],{"x":117,"y":107,"fill":90,"style":108,"textAnchor":118},"216.4","middle","Stored by browser?",[70,121],{"x":122,"y":100,"width":114,"height":102,"rx":74,"fill":90,"stroke":90,"style":103},"319.5",[93,124,126],{"x":125,"y":107,"fill":90,"style":108,"textAnchor":118},"422.6","Must revalidate?",[70,128],{"x":129,"y":100,"width":114,"height":102,"rx":74,"fill":90,"stroke":90,"style":103},"525.8",[93,131,133],{"x":132,"y":107,"fill":90,"style":108,"textAnchor":118},"628.9","bfcache",[70,135],{"x":95,"y":136,"width":101,"height":102,"rx":74,"fill":89,"stroke":90,"style":137},"86.0","stroke-opacity:0.35",[93,139,36],{"x":106,"y":140,"fill":90,"style":108,"textAnchor":109},"105.5",[70,142],{"x":113,"y":136,"width":114,"height":102,"rx":74,"fill":143,"stroke":144,"style":145},"#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[93,147,149],{"x":117,"y":140,"fill":90,"style":148,"textAnchor":118},"font-size:12px","no",[70,151],{"x":122,"y":136,"width":114,"height":102,"rx":74,"fill":90,"stroke":90,"style":103},[93,153,154],{"x":125,"y":140,"fill":90,"style":148,"textAnchor":118},"n\u002Fa",[70,156],{"x":129,"y":136,"width":114,"height":102,"rx":74,"fill":143,"stroke":144,"style":145},[93,158,159],{"x":132,"y":140,"fill":90,"style":148,"textAnchor":118},"historically blocks",[70,161],{"x":95,"y":162,"width":101,"height":102,"rx":74,"fill":89,"stroke":90,"style":137},"116.0",[93,164,49],{"x":106,"y":165,"fill":90,"style":108,"textAnchor":109},"135.5",[70,167],{"x":113,"y":162,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},"#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[93,171,172],{"x":117,"y":165,"fill":90,"style":148,"textAnchor":118},"yes",[70,174],{"x":122,"y":162,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,176,177],{"x":125,"y":165,"fill":90,"style":148,"textAnchor":118},"every use",[70,179],{"x":129,"y":162,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,181,182],{"x":132,"y":165,"fill":90,"style":148,"textAnchor":118},"eligible",[70,184],{"x":95,"y":185,"width":101,"height":102,"rx":74,"fill":89,"stroke":90,"style":137},"146.0",[93,187,53],{"x":106,"y":188,"fill":90,"style":108,"textAnchor":109},"165.5",[70,190],{"x":113,"y":185,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,192,193],{"x":117,"y":188,"fill":90,"style":148,"textAnchor":118},"browser only",[70,195],{"x":122,"y":185,"width":114,"height":102,"rx":74,"fill":90,"stroke":90,"style":103},[93,197,198],{"x":125,"y":188,"fill":90,"style":148,"textAnchor":118},"per max-age",[70,200],{"x":129,"y":185,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,202,182],{"x":132,"y":188,"fill":90,"style":148,"textAnchor":118},[70,204],{"x":95,"y":205,"width":101,"height":102,"rx":74,"fill":89,"stroke":90,"style":137},"176.0",[93,207,209],{"x":106,"y":208,"fill":90,"style":108,"textAnchor":109},"195.5","max-age=0",[70,211],{"x":113,"y":205,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,213,172],{"x":117,"y":208,"fill":90,"style":148,"textAnchor":118},[70,215],{"x":122,"y":205,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,217,218],{"x":125,"y":208,"fill":90,"style":148,"textAnchor":118},"when stale (immediately)",[70,220],{"x":129,"y":205,"width":114,"height":102,"rx":74,"fill":168,"stroke":168,"style":169},[93,222,182],{"x":132,"y":208,"fill":90,"style":148,"textAnchor":118},[224,225,227],"h2",{"id":226},"rapid-diagnosis","Rapid Diagnosis",[229,230,231,242,248,260],"ul",{},[232,233,234,238,239,241],"li",{},[235,236,237],"strong",{},"Check HTML response headers"," on key templates (Network panel → document → Headers). Note ",[30,240,36],{}," occurrences.",[232,243,244,247],{},[235,245,246],{},"Find where it is set."," Framework defaults, authentication middleware, CDN page rules and reverse proxies are common sources; one global rule often applies to public pages too.",[232,249,250,68,253,256,257,259],{},[235,251,252],{},"Correlate with bfcache field data.",[30,254,255],{},"notRestoredReasons"," includes a reason for ",[30,258,36],{}," main resources; rank templates by how often it appears.",[232,261,262,265],{},[235,263,264],{},"Classify content."," Which templates show data that must never be kept on disk (banking, health records)? Which are just \"logged-in\" or \"dynamic\"?",[224,267,269],{"id":268},"root-cause-analysis","Root Cause Analysis",[15,271,272,275,276,278],{},[235,273,274],{},"1. Global no-store as a default."," Security checklists recommend ",[30,277,36],{}," for sensitive pages; teams apply it to all HTML for simplicity.",[15,280,281,68,284,286,287,289],{},[235,282,283],{},"2. Confusing no-store with no-cache.",[30,285,49],{}," means \"revalidate before use\" — exactly what most teams want for HTML — but ",[30,288,36],{}," is chosen because the name sounds stronger.",[15,291,292,68,295,297,298,300],{},[235,293,294],{},"3. CDN safety.",[30,296,36],{}," is used to stop CDNs caching personalised pages; ",[30,299,53],{}," achieves that without forbidding browser storage.",[15,302,303,306,307,309],{},[235,304,305],{},"4. Logout concerns."," Teams fear a user pressing Back after logout and seeing account data; this is a real concern but solvable without ",[30,308,36],{}," on every page.",[15,311,312],{},[61,313,68,316,68,319,68,322,68,324,68,341,68,344,68,346,68,351,68,357,68,360,68,365,68,374,68,379,68,383,68,388,68,391,68,395,68,397,68,400,68,403,68,406,68,409,68,412,68,415,68,419,68,421,68,424,68,427,68,430,68,434,68,437,68,441,68,445,68],{"viewBox":314,"width":64,"role":65,"ariaLabel":315,"style":67},"0 0 760 341","Decision sequence for choosing a Cache-Control header for HTML responses based on sensitivity and personalisation.",[70,317],{"className":318,"x":74,"y":74,"width":64,"height":64,"fill":75},[73],[77,320,321],{},"Which header should this HTML response use?",[81,323,315],{},[325,326,327],"defs",{},[328,329,336],"marker",{"id":330,"viewBox":331,"refX":332,"refY":333,"markerWidth":334,"markerHeight":334,"orient":335},"fa443060a0","0 0 10 10","9","5","7","auto-start-reverse",[337,338],"path",{"d":339,"fill":90,"style":340},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[70,342],{"x":85,"y":85,"width":86,"height":343,"rx":88,"fill":89,"stroke":90,"style":91},"339",[93,345,321],{"x":95,"y":96,"fill":90,"style":97},[70,347],{"x":95,"y":100,"width":348,"height":349,"rx":350,"fill":90,"stroke":90,"style":103},"320.0","35.0","6",[93,352,356],{"x":353,"y":354,"fill":90,"style":355,"textAnchor":118},"188.0","78.0","font-size:13px;font-weight:700","Contains highly sensitive data (finance, health)?",[70,358],{"x":359,"y":100,"width":348,"height":349,"rx":350,"fill":143,"stroke":144,"style":145},"412.0",[93,361,364],{"x":362,"y":354,"fill":90,"style":363,"textAnchor":118},"572.0","font-size:12.5px","no-store (accept no bfcache)",[366,367],"line",{"x1":368,"y1":369,"x2":370,"y2":369,"stroke":90,"strokeWidth":371,"style":372,"markerEnd":373},"348.0","73.5","410.0","1.5","stroke-opacity:0.6","url(#fa443060a0)",[93,375,172],{"x":376,"y":377,"fill":168,"style":378,"textAnchor":118},"380.0","66.5","font-size:11.5px;font-weight:700",[366,380],{"x1":353,"y1":381,"x2":353,"y2":382,"stroke":90,"strokeWidth":371,"style":372,"markerEnd":373},"91.0","125.0",[93,384,149],{"x":385,"y":386,"fill":387,"style":378},"196.0","113.0","#51617a",[70,389],{"x":95,"y":390,"width":348,"height":349,"rx":350,"fill":90,"stroke":90,"style":103},"127.0",[93,392,394],{"x":353,"y":393,"fill":90,"style":355,"textAnchor":118},"149.0","Personalised for the logged-in user?",[70,396],{"x":359,"y":390,"width":348,"height":349,"rx":350,"fill":168,"stroke":168,"style":169},[93,398,399],{"x":362,"y":393,"fill":90,"style":363,"textAnchor":118},"private, no-cache",[366,401],{"x1":368,"y1":402,"x2":370,"y2":402,"stroke":90,"strokeWidth":371,"style":372,"markerEnd":373},"144.5",[93,404,172],{"x":376,"y":405,"fill":168,"style":378,"textAnchor":118},"137.5",[366,407],{"x1":353,"y1":408,"x2":353,"y2":385,"stroke":90,"strokeWidth":371,"style":372,"markerEnd":373},"162.0",[93,410,149],{"x":385,"y":411,"fill":387,"style":378},"184.0",[70,413],{"x":95,"y":414,"width":348,"height":349,"rx":350,"fill":90,"stroke":90,"style":103},"198.0",[93,416,418],{"x":353,"y":417,"fill":90,"style":355,"textAnchor":118},"220.0","Public but must always be fresh?",[70,420],{"x":359,"y":414,"width":348,"height":349,"rx":350,"fill":168,"stroke":168,"style":169},[93,422,423],{"x":362,"y":417,"fill":90,"style":363,"textAnchor":118},"no-cache (or short s-maxage at the CDN)",[366,425],{"x1":368,"y1":426,"x2":370,"y2":426,"stroke":90,"strokeWidth":371,"style":372,"markerEnd":373},"215.5",[93,428,172],{"x":376,"y":429,"fill":168,"style":378,"textAnchor":118},"208.5",[366,431],{"x1":353,"y1":432,"x2":353,"y2":433,"stroke":90,"strokeWidth":371,"style":372,"markerEnd":373},"233.0","267.0",[93,435,149],{"x":385,"y":436,"fill":387,"style":378},"255.0",[70,438],{"x":95,"y":439,"width":348,"height":440,"rx":350,"fill":143,"stroke":144,"style":145},"269.0","50.0",[93,442,444],{"x":353,"y":443,"fill":90,"style":363,"textAnchor":118},"290.5","Public, cacheable — max-age \u002F s-maxage with",[93,446,448],{"x":353,"y":447,"fill":90,"style":363,"textAnchor":118},"306.5","revalidation",[224,450,452],{"id":451},"step-by-step-resolution","Step-by-Step Resolution",[454,455,457],"h3",{"id":456},"_1-classify-templates-by-sensitivity","1. Classify templates by sensitivity",[15,459,460,461,463],{},"Make an explicit list: public templates, personalised-but-ordinary templates (account dashboard, cart), and sensitive templates (payment details, medical records). Only the last group needs ",[30,462,36],{},".",[454,465,467],{"id":466},"_2-set-headers-per-class","2. Set headers per class",[469,470,475],"pre",{"className":471,"code":472,"language":473,"meta":474,"style":474},"language-nginx shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","# Public HTML: cacheable at the edge, revalidated by browsers.\nlocation \u002F { add_header Cache-Control \"public, max-age=0, s-maxage=300, must-revalidate\"; }\n# Logged-in pages: browser may keep them (bfcache-eligible), CDN must not.\nlocation \u002Faccount\u002F { add_header Cache-Control \"private, no-cache\"; }\n# Sensitive pages: never stored.\nlocation \u002Faccount\u002Fpayment-methods\u002F { add_header Cache-Control \"no-store\"; }\n# trade-off: per-path rules need maintenance as routes change. Prefer setting\n# headers in the application per route type, with a safe default (private,\n# no-cache) for anything authenticated that is not explicitly classified.\n","nginx","",[30,476,477,485,513,519,538,544,563,569,575],{"__ignoreMap":474},[478,479,481],"span",{"class":366,"line":480},1,[478,482,484],{"class":483},"sjfSM","# Public HTML: cacheable at the edge, revalidated by browsers.\n",[478,486,488,492,496,500,503,506,510],{"class":366,"line":487},2,[478,489,491],{"class":490},"sPARh","location",[478,493,495],{"class":494},"sQw3B"," \u002F ",[478,497,499],{"class":498},"saISM","{",[478,501,502],{"class":490}," add_header ",[478,504,505],{"class":498},"Cache-Control ",[478,507,509],{"class":508},"sZ8jY","\"public, max-age=0, s-maxage=300, must-revalidate\"",[478,511,512],{"class":498},"; }\n",[478,514,516],{"class":366,"line":515},3,[478,517,518],{"class":483},"# Logged-in pages: browser may keep them (bfcache-eligible), CDN must not.\n",[478,520,522,524,527,529,531,533,536],{"class":366,"line":521},4,[478,523,491],{"class":490},[478,525,526],{"class":494}," \u002Faccount\u002F ",[478,528,499],{"class":498},[478,530,502],{"class":490},[478,532,505],{"class":498},[478,534,535],{"class":508},"\"private, no-cache\"",[478,537,512],{"class":498},[478,539,541],{"class":366,"line":540},5,[478,542,543],{"class":483},"# Sensitive pages: never stored.\n",[478,545,547,549,552,554,556,558,561],{"class":366,"line":546},6,[478,548,491],{"class":490},[478,550,551],{"class":494}," \u002Faccount\u002Fpayment-methods\u002F ",[478,553,499],{"class":498},[478,555,502],{"class":490},[478,557,505],{"class":498},[478,559,560],{"class":508},"\"no-store\"",[478,562,512],{"class":498},[478,564,566],{"class":366,"line":565},7,[478,567,568],{"class":483},"# trade-off: per-path rules need maintenance as routes change. Prefer setting\n",[478,570,572],{"class":366,"line":571},8,[478,573,574],{"class":483},"# headers in the application per route type, with a safe default (private,\n",[478,576,578],{"class":366,"line":577},9,[478,579,580],{"class":483},"# no-cache) for anything authenticated that is not explicitly classified.\n",[15,582,583],{},"Expected outcome: most templates become bfcache-eligible; sensitive ones stay protected.",[454,585,587],{"id":586},"_3-handle-logout-and-session-expiry-on-restore","3. Handle logout and session expiry on restore",[15,589,590,591,594],{},"If a page is restored from bfcache after the session ended, check on ",[30,592,593],{},"pageshow"," and redirect.",[469,596,600],{"className":597,"code":598,"language":599,"meta":474,"style":474},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","addEventListener('pageshow', async (event) => {\n  if (!event.persisted) return;\n  const res = await fetch('\u002Fapi\u002Fsession', { cache: 'no-store', credentials: 'same-origin' });\n  if (res.status === 401) location.replace('\u002Flogin?expired=1');\n});\n\u002F\u002F trade-off: the restored page is briefly visible before the redirect. For\n\u002F\u002F templates where even a moment's display is unacceptable, keep no-store.\n","javascript",[30,601,602,635,654,692,719,724,729],{"__ignoreMap":474},[478,603,604,608,611,614,617,620,623,626,629,632],{"class":366,"line":480},[478,605,607],{"class":606},"smZ65","addEventListener",[478,609,610],{"class":498},"(",[478,612,613],{"class":508},"'pageshow'",[478,615,616],{"class":498},", ",[478,618,619],{"class":490},"async",[478,621,622],{"class":498}," (",[478,624,625],{"class":494},"event",[478,627,628],{"class":498},") ",[478,630,631],{"class":490},"=>",[478,633,634],{"class":498}," {\n",[478,636,637,640,642,645,648,651],{"class":366,"line":487},[478,638,639],{"class":490},"  if",[478,641,622],{"class":498},[478,643,644],{"class":490},"!",[478,646,647],{"class":498},"event.persisted) ",[478,649,650],{"class":490},"return",[478,652,653],{"class":498},";\n",[478,655,656,659,663,666,669,672,674,677,680,683,686,689],{"class":366,"line":515},[478,657,658],{"class":490},"  const",[478,660,662],{"class":661},"sPXB4"," res",[478,664,665],{"class":490}," =",[478,667,668],{"class":490}," await",[478,670,671],{"class":606}," fetch",[478,673,610],{"class":498},[478,675,676],{"class":508},"'\u002Fapi\u002Fsession'",[478,678,679],{"class":498},", { cache: ",[478,681,682],{"class":508},"'no-store'",[478,684,685],{"class":498},", credentials: ",[478,687,688],{"class":508},"'same-origin'",[478,690,691],{"class":498}," });\n",[478,693,694,696,699,702,705,708,711,713,716],{"class":366,"line":521},[478,695,639],{"class":490},[478,697,698],{"class":498}," (res.status ",[478,700,701],{"class":490},"===",[478,703,704],{"class":661}," 401",[478,706,707],{"class":498},") location.",[478,709,710],{"class":606},"replace",[478,712,610],{"class":498},[478,714,715],{"class":508},"'\u002Flogin?expired=1'",[478,717,718],{"class":498},");\n",[478,720,721],{"class":366,"line":540},[478,722,723],{"class":498},"});\n",[478,725,726],{"class":366,"line":546},[478,727,728],{"class":483},"\u002F\u002F trade-off: the restored page is briefly visible before the redirect. For\n",[478,730,731],{"class":366,"line":565},[478,732,733],{"class":483},"\u002F\u002F templates where even a moment's display is unacceptable, keep no-store.\n",[15,735,736],{},"Expected outcome: logged-out users never interact with stale authenticated pages.",[454,738,740],{"id":739},"_4-verify-cdn-behaviour","4. Verify CDN behaviour",[15,742,743,744,746,747,463],{},"Confirm the CDN respects ",[30,745,53],{}," (does not cache) and that no edge rule rewrites headers back to ",[30,748,36],{},[15,750,751],{},[61,752,68,755,68,758,68,761,68,763,68,766,68,768,68,775,68,782,68,787,68,791,68,796,68,800,68,804,68,808,68],{"viewBox":753,"width":64,"role":65,"ariaLabel":754,"style":67},"0 0 760 163","Bar chart of back\u002Fforward navigations restored from bfcache under three header policies for an authenticated application.",[70,756],{"className":757,"x":74,"y":74,"width":64,"height":64,"fill":75},[73],[77,759,760],{},"bfcache restoration rate by header policy (logged-in app)",[81,762,754],{},[70,764],{"x":85,"y":85,"width":86,"height":765,"rx":88,"fill":89,"stroke":90,"style":91},"161",[93,767,760],{"x":95,"y":96,"fill":90,"style":97},[93,769,774],{"x":770,"y":771,"fill":90,"style":772,"textAnchor":773},"245.9","70.0","font-size:13px","end","no-store on all HTML",[70,776],{"x":777,"y":100,"width":778,"height":779,"rx":780,"fill":143,"stroke":144,"style":781},"257.9","20.0","19","3","fill-opacity:0.7;stroke-opacity:0.9",[93,783,786],{"x":784,"y":771,"fill":90,"style":785},"283.9","font-size:12px;font-weight:600","4%",[93,788,790],{"x":770,"y":789,"fill":90,"style":772,"textAnchor":773},"101.0","private, no-cache (sensitive: no-store)",[70,792],{"x":777,"y":793,"width":794,"height":779,"rx":780,"fill":168,"stroke":168,"style":795},"87.0","315.1","fill-opacity:0.55;stroke-opacity:0.9",[93,797,799],{"x":798,"y":789,"fill":90,"style":785},"579.0","63%",[93,801,803],{"x":770,"y":802,"fill":90,"style":772,"textAnchor":773},"132.0","+ unload and socket fixes",[70,805],{"x":777,"y":806,"width":807,"height":779,"rx":780,"fill":168,"stroke":168,"style":795},"118.0","410.1",[93,809,811],{"x":810,"y":802,"fill":90,"style":785},"674.0","82%",[224,813,815],{"id":814},"verification","Verification",[15,817,818,819,822,823,825],{},"Check headers on each template class with ",[30,820,821],{},"curl -sI",". Run the DevTools bfcache test on public and account pages: they should restore; sensitive pages should not. In RUM, the share of misses attributed to ",[30,824,36],{}," should drop to the sensitive templates only. Have your security team review the classification.",[224,827,829],{"id":828},"worked-example-a-saas-dashboard","Worked Example: A SaaS Dashboard",[15,831,832,833,835,836,838,839,841,842,844],{},"A SaaS application's framework sent ",[30,834,32],{}," on every server-rendered response. Users frequently moved between a project list and project pages with Back; every return reloaded the list, taking 1.8s on average on laptops with slow office Wi-Fi. After classifying templates, the team set ",[30,837,399],{}," on the list and project pages and kept ",[30,840,36],{}," only on billing and API-key pages, and added the session check on ",[30,843,593],{},". Back navigations to the project list became instant for 78% of navigations in Chromium, and server load from list requests fell by roughly a quarter.",[224,846,848],{"id":847},"common-mistakes","Common Mistakes",[229,850,851,857,869,875],{},[232,852,853,856],{},[235,854,855],{},"Removing no-store from everything."," Sensitive pages still need it; classify first.",[232,858,859,865,866,868],{},[235,860,861,862,864],{},"Using ",[30,863,49],{}," and expecting it to stop CDN caching."," Pair it with ",[30,867,53],{}," for personalised pages.",[232,870,871,874],{},[235,872,873],{},"Forgetting the session check."," Without it, a restored page after logout may still show data until the user interacts.",[232,876,877,885],{},[235,878,879,880,882,883,463],{},"Assuming ",[30,881,209],{}," equals ",[30,884,36],{}," It allows storage and requires revalidation; it is often what teams actually want.",[224,887,889],{"id":888},"edge-cases","Edge Cases",[15,891,892,895,896,463],{},[235,893,894],{},"Pages with CSRF tokens."," Restored pages carry the token they were rendered with; if tokens rotate per page view, a form submitted from a restored page may fail. Use per-session tokens or refresh the token on ",[30,897,593],{},[15,899,900,903,904,906],{},[235,901,902],{},"Shared devices."," On kiosks or shared computers, policy may require ",[30,905,36],{}," more broadly; that is a legitimate business decision with a performance cost.",[15,908,909,912,913,915],{},[235,910,911],{},"Embedded third-party content."," A cross-origin iframe served with ",[30,914,36],{}," can also affect eligibility; check frame-level reasons.",[15,917,918,921,922,924],{},[235,919,920],{},"Chromium experiments."," Chromium has tested restoring ",[30,923,36],{}," pages when no cookies changed; behaviour may differ across versions, so measure rather than assume.",[224,926,928],{"id":927},"coordinating-with-security-reviews","Coordinating With Security Reviews",[15,930,931,932,934,935,937,938,940,941,943],{},"Header changes on authenticated pages deserve a short written rationale, because ",[30,933,36],{}," often appears in security checklists and auditors look for it. Document, per template class, what the page contains, who can see it, what the realistic threat is (shared devices, back-button exposure after logout), and which control addresses it — ",[30,936,36],{},", a session check on restore, or short session lifetimes. Most security teams accept ",[30,939,399],{}," plus a restore-time session check for ordinary account pages once the trade-off is explained in those terms, and keep ",[30,942,36],{}," for the handful of pages where any on-disk storage is unacceptable.",[224,945,947],{"id":946},"faq","FAQ",[949,950,953,957],"details",{"className":951},[952],"faq-item",[954,955,956],"summary",{},"Does no-cache mean the page will not be cached?",[15,958,959],{},"No — it means the page may be stored but must be revalidated with the server before each reuse. It is the right default for HTML that must always be current, and it does not block bfcache.",[949,961,963,966],{"className":962},[952],[954,964,965],{},"Is bfcache restoration a security risk for authenticated pages?",[15,967,968,969,971,972,463],{},"The page is restored in the same tab, for the same user who saw it moments before, from memory. The main risk is logout or session expiry on shared devices; the ",[30,970,593],{}," session check addresses it. Highly sensitive pages can keep ",[30,973,36],{},[949,975,977,980],{"className":976},[952],[954,978,979],{},"What does private actually prevent?",[15,981,982],{},"It tells shared caches (CDNs, proxies) not to store the response; the user's own browser may still cache it. That is usually exactly what personalised pages need.",[949,984,986,989],{"className":985},[952],[954,987,988],{},"Should API responses use no-store?",[15,990,991,992,996],{},"API caching is a separate decision covered in ",[19,993,995],{"href":994},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fcdn-edge-caching-configuration\u002Fcaching-api-responses-at-the-cdn\u002F","caching API responses at the CDN",". API headers do not affect the document's bfcache eligibility, though the data they return may need refreshing on restore.",[949,998,1000,1003],{"className":999},[952],[954,1001,1002],{},"Can I test the effect of a header change before deploying?",[15,1004,1005,1006,1008],{},"Yes: DevTools' network request overrides let you change response headers locally, then run the bfcache test. That confirms ",[30,1007,36],{}," was the only blocker before you change server configuration.",[224,1010,1012],{"id":1011},"related","Related",[229,1014,1015,1022,1029],{},[232,1016,1017,1021],{},[19,1018,1020],{"href":1019},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fhttp-cache-control-headers-explained\u002Fno-cache-vs-no-store-vs-max-age-0\u002F","no-cache vs no-store vs max-age=0"," — the directives in depth.",[232,1023,1024,1028],{},[19,1025,1027],{"href":1026},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fhttp-cache-control-headers-explained\u002Fcache-control-for-html-documents\u002F","Cache-Control for HTML documents"," — choosing HTML policies generally.",[232,1030,1031,1035],{},[19,1032,1034],{"href":1033},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fedge-compute-and-dynamic-caching\u002Fcaching-html-for-logged-in-users-safely\u002F","Caching HTML for logged-in users safely"," — the edge side of personalised pages.",[1037,1038,1040],"script",{"type":1039},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"Cache-Control no-store and the Back\u002FForward Cache\",\n  \"description\": \"How Cache-Control no-store interacts with the back\u002Fforward cache, when the header is required for security, and how to keep public pages instant.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Classify templates by sensitivity\",\n      \"text\": \"Make an explicit list: public templates, personalised-but-ordinary templates (account dashboard, cart), and sensitive templates (payment details, medical records).\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Set headers per class\",\n      \"text\": \"Expected outcome: most templates become bfcache-eligible; sensitive ones stay protected.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Handle logout and session expiry on restore\",\n      \"text\": \"If a page is restored from bfcache after the session ended, check on pageshow and redirect.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Verify CDN behaviour\",\n      \"text\": \"Confirm the CDN respects private (does not cache) and that no edge rule rewrites headers back to no-store.\"\n    }\n  ]\n}\n",[1037,1042,1043],{"type":1039},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"Cache-Control no-store and the Back\u002FForward Cache\",\n  \"description\": \"How Cache-Control no-store interacts with the back\u002Fforward cache, when the header is required for security, and how to keep public pages instant.\",\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\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002F\"\n  }\n}\n",[1037,1045,1046],{"type":1039},"\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\": \"Back\u002FForward Cache (bfcache)\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Cache-Control no-store and bfcache\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002F\"\n    }\n  ]\n}\n",[1048,1049,1050],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}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 .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);}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}",{"title":474,"searchDepth":487,"depth":487,"links":1052},[1053,1054,1055,1061,1062,1063,1064,1065,1066,1067],{"id":226,"depth":487,"text":227},{"id":268,"depth":487,"text":269},{"id":451,"depth":487,"text":452,"children":1056},[1057,1058,1059,1060],{"id":456,"depth":515,"text":457},{"id":466,"depth":515,"text":467},{"id":586,"depth":515,"text":587},{"id":739,"depth":515,"text":740},{"id":814,"depth":487,"text":815},{"id":828,"depth":487,"text":829},{"id":847,"depth":487,"text":848},{"id":888,"depth":487,"text":889},{"id":927,"depth":487,"text":928},{"id":946,"depth":487,"text":947},{"id":1011,"depth":487,"text":1012},"How Cache-Control no-store interacts with the back\u002Fforward cache, when the header is required for security, and how to keep public pages instant.","md",{"slug":1071,"type":1072,"breadcrumb":1073,"datePublished":1081,"dateModified":1081},"cache-control-no-store-and-bfcache","article",[1074,1077,1078,1079],{"name":1075,"url":1076},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1080},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002F","2026-10-06",true,"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache",{"title":13,"description":1085},"no-store on HTML has historically made pages ineligible for bfcache. Learn when no-store is truly needed, safer alternatives, and how to protect sensitive pages.","advanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002Findex","kJcy89dI2Oa8gL3J_EYMoYbMvwbolDGA584DT5L8szk",[1089,1092],{"title":22,"path":1090,"stem":1091,"children":-1},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache","advanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Findex",{"title":1093,"path":1094,"stem":1095,"children":-1},"Fixing bfcache Eligibility Blockers","\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers","advanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers\u002Findex",1791308072907]