[{"data":1,"prerenderedAt":1051},["ShallowReactive",2],{"content:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers":3,"surroundings:\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers":1043},{"id":4,"title":5,"body":6,"description":1022,"extension":1023,"meta":1024,"navigation":1036,"path":1037,"seo":1038,"stem":1041,"__hash__":1042},"content\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers\u002Findex.md","Fixing bfcache Eligibility Blockers",{"type":7,"value":8,"toc":1003},"minimark",[9,14,29,32,186,191,253,257,270,280,286,292,298,385,389,394,508,515,519,627,630,634,641,649,663,667,670,789,793,796,800,814,818,851,855,864,870,876,885,889,898,902,914,923,935,944,961,965,988,993,996,999],[10,11,13],"h1",{"id":12},"how-to-fix-bfcache-eligibility-blockers","How to Fix bfcache Eligibility Blockers",[15,16,17,18,23,24,28],"p",{},"This guide is the hands-on workflow for ",[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",". The scenario: your field data shows that most back navigations reload the page instead of restoring it, and DevTools lists a handful of reasons when you test. Each reason corresponds to an API or header that the browser cannot safely freeze and resume. Most have a standard replacement that keeps the feature and restores eligibility.",[15,30,31],{},"Work in order of field frequency rather than DevTools order. A blocker that affects 60% of misses is worth fixing first even if it looks minor; a blocker that appears only when a rare third-party widget loads can wait.",[15,33,34],{},[35,36,42,43,42,50,42,54,42,57,42,75,42,83,42,89,42,97,42,104,42,109,42,113,42,116,42,120,42,123,42,126,42,129,42,133,42,136,42,139,42,145,42,149,42,152,42,155,42,158,42,162,42,165,42,174,42,178,42,182,42],"svg",{"viewBox":37,"width":38,"role":39,"ariaLabel":40,"style":41},"0 0 760 149","100%","img","Steps for systematically finding and fixing bfcache blockers from field data to verification.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[44,45],"rect",{"className":46,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],"svg-canvas","0","#ffffff",[51,52,53],"title",{},"Blocker-fixing workflow",[55,56,40],"desc",{},[58,59,60],"defs",{},[61,62,69],"marker",{"id":63,"viewBox":64,"refX":65,"refY":66,"markerWidth":67,"markerHeight":67,"orient":68},"fab50e8cfd","0 0 10 10","9","5","7","auto-start-reverse",[70,71],"path",{"d":72,"fill":73,"style":74},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[44,76],{"x":77,"y":77,"width":78,"height":79,"rx":80,"fill":81,"stroke":73,"style":82},"1","758","147","10","none","stroke-opacity:0.18",[84,85,53],"text",{"x":86,"y":87,"fill":73,"style":88},"28.0","34.0","font-size:16px;font-weight:700",[44,90],{"x":86,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"56.0","108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[84,98,103],{"x":99,"y":100,"fill":73,"style":101,"textAnchor":102},"82.4","78.0","font-size:13px;font-weight:700","middle","Field reasons",[84,105,108],{"x":99,"y":106,"fill":73,"style":107,"textAnchor":102},"96.0","font-size:12px","from the reasons",[84,110,112],{"x":99,"y":111,"fill":73,"style":107,"textAnchor":102},"112.0","API",[44,114],{"x":115,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"176.8",[84,117,119],{"x":118,"y":100,"fill":73,"style":101,"textAnchor":102},"231.2","Rank",[84,121,122],{"x":118,"y":106,"fill":73,"style":107,"textAnchor":102},"by share of",[84,124,125],{"x":118,"y":111,"fill":73,"style":107,"textAnchor":102},"misses",[44,127],{"x":128,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"325.6",[84,130,132],{"x":131,"y":100,"fill":73,"style":101,"textAnchor":102},"380.0","Reproduce",[84,134,135],{"x":131,"y":106,"fill":73,"style":107,"textAnchor":102},"DevTools bfcache",[84,137,138],{"x":131,"y":111,"fill":73,"style":107,"textAnchor":102},"test",[44,140],{"x":141,"y":91,"width":92,"height":93,"rx":94,"fill":142,"stroke":143,"style":144},"474.4","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[84,146,148],{"x":147,"y":100,"fill":73,"style":101,"textAnchor":102},"528.8","Replace API",[84,150,151],{"x":147,"y":106,"fill":73,"style":107,"textAnchor":102},"standard",[84,153,154],{"x":147,"y":111,"fill":73,"style":107,"textAnchor":102},"alternative",[44,156],{"x":157,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"623.2",[84,159,161],{"x":160,"y":100,"fill":73,"style":101,"textAnchor":102},"677.6","Verify",[84,163,164],{"x":160,"y":106,"fill":73,"style":107,"textAnchor":102},"lab + field rate",[166,167],"line",{"x1":168,"y1":169,"x2":170,"y2":169,"stroke":73,"strokeWidth":171,"style":172,"markerEnd":173},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fab50e8cfd)",[166,175],{"x1":176,"y1":169,"x2":177,"y2":169,"stroke":73,"strokeWidth":171,"style":172,"markerEnd":173},"285.6","323.6",[166,179],{"x1":180,"y1":169,"x2":181,"y2":169,"stroke":73,"strokeWidth":171,"style":172,"markerEnd":173},"434.4","472.4",[166,183],{"x1":184,"y1":169,"x2":185,"y2":169,"stroke":73,"strokeWidth":171,"style":172,"markerEnd":173},"583.2","621.2",[187,188,190],"h2",{"id":189},"rapid-diagnosis","Rapid Diagnosis",[192,193,194,202,224,247],"ul",{},[195,196,197,201],"li",{},[198,199,200],"strong",{},"Run DevTools → Application → Back\u002Fforward cache → Test."," Note each reason and its category: \"Actionable\", \"Pending support\" or \"Not actionable\".",[195,203,204,42,207,211,212,215,216,219,220,223],{},[198,205,206],{},"Collect field reasons.",[208,209,210],"code",{},"performance.getEntriesByType('navigation')[0].notRestoredReasons"," on ",[208,213,214],{},"pageshow"," when ",[208,217,218],{},"persisted"," is false and the type is ",[208,221,222],{},"back_forward",".",[195,225,226,229,230,233,234,233,237,233,240,233,243,246],{},[198,227,228],{},"Search the codebase"," for ",[208,231,232],{},"addEventListener('unload'",", ",[208,235,236],{},"onunload",[208,238,239],{},"beforeunload",[208,241,242],{},"new WebSocket(",[208,244,245],{},"RTCPeerConnection",", and IndexedDB transactions held across awaits.",[195,248,249,252],{},[198,250,251],{},"List third-party scripts and iframes"," on the template; many blockers live there.",[187,254,256],{"id":255},"root-cause-analysis-the-blockers-and-why-they-block","Root Cause Analysis: The Blockers and Why They Block",[15,258,259,266,267,269],{},[198,260,261,262,265],{},"1. ",[208,263,264],{},"unload"," handlers."," Code in ",[208,268,264],{}," assumes the page is being destroyed. If the browser froze the page instead, that assumption would break, so Chromium treats pages with unload handlers as ineligible on desktop (and Firefox similarly).",[15,271,272,279],{},[198,273,274,275,278],{},"2. ",[208,276,277],{},"Cache-Control: no-store"," on the document."," The header signals the content must not be stored; browsers have historically refused to keep such pages in bfcache.",[15,281,282,285],{},[198,283,284],{},"3. Open network connections."," WebSockets, WebRTC peer connections and in-flight fetches cannot be paused indefinitely.",[15,287,288,291],{},[198,289,290],{},"4. Locks and transactions."," Unfinished IndexedDB transactions, Web Locks or other shared resources held by the page would block other tabs while frozen.",[15,293,294,297],{},[198,295,296],{},"5. Blocked frames."," Any of the above in an iframe — including cross-origin ads and embeds — blocks the whole page.",[15,299,300],{},[35,301,42,304,42,307,42,310,42,312,42,315,42,317,42,324,42,331,42,336,42,339,42,344,42,348,42,352,42,356,42,360,42,364,42,368,42,372,42,376,42,381,42],{"viewBox":302,"width":38,"role":39,"ariaLabel":303,"style":41},"0 0 760 225","Bar chart of the distribution of bfcache miss reasons from field data on a typical content site.",[44,305],{"className":306,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,308,309],{},"Share of bfcache misses by reason (typical content site)",[55,311,303],{},[44,313],{"x":77,"y":77,"width":78,"height":314,"rx":80,"fill":81,"stroke":73,"style":82},"223",[84,316,309],{"x":86,"y":87,"fill":73,"style":88},[84,318,323],{"x":319,"y":320,"fill":73,"style":321,"textAnchor":322},"166.5","70.0","font-size:13px","end","unload handler",[44,325],{"x":326,"y":91,"width":327,"height":328,"rx":329,"fill":142,"stroke":143,"style":330},"178.5","489.5","19","3","fill-opacity:0.7;stroke-opacity:0.9",[84,332,335],{"x":333,"y":320,"fill":73,"style":334},"674.0","font-size:12px;font-weight:600","48%",[84,337,277],{"x":319,"y":338,"fill":73,"style":321,"textAnchor":322},"101.0",[44,340],{"x":326,"y":341,"width":342,"height":328,"rx":329,"fill":95,"stroke":95,"style":343},"87.0","214.1","fill-opacity:0.55;stroke-opacity:0.9",[84,345,347],{"x":346,"y":338,"fill":73,"style":334},"398.7","21%",[84,349,351],{"x":319,"y":350,"fill":73,"style":321,"textAnchor":322},"132.0","Third-party iframe",[44,353],{"x":326,"y":354,"width":355,"height":328,"rx":329,"fill":95,"stroke":95,"style":343},"118.0","142.8",[84,357,359],{"x":358,"y":350,"fill":73,"style":334},"327.3","14%",[84,361,363],{"x":319,"y":362,"fill":73,"style":321,"textAnchor":322},"163.0","WebSocket open",[44,365],{"x":326,"y":366,"width":367,"height":328,"rx":329,"fill":95,"stroke":95,"style":343},"149.0","91.8",[84,369,371],{"x":370,"y":362,"fill":73,"style":334},"276.3","9%",[84,373,375],{"x":319,"y":374,"fill":73,"style":321,"textAnchor":322},"194.0","Other",[44,377],{"x":326,"y":378,"width":379,"height":328,"rx":329,"fill":73,"stroke":73,"style":380},"180.0","81.6","fill-opacity:0.7;stroke-opacity:0.4",[84,382,384],{"x":383,"y":374,"fill":73,"style":334},"266.1","8%",[187,386,388],{"id":387},"step-by-step-resolution","Step-by-Step Resolution",[390,391,393],"h3",{"id":392},"_1-replace-unload-with-pagehide-or-visibilitychange","1. Replace unload with pagehide or visibilitychange",[395,396,401],"pre",{"className":397,"code":398,"language":399,"meta":400,"style":400},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Before\naddEventListener('unload', () => navigator.sendBeacon('\u002Flog', JSON.stringify(pending)));\n\u002F\u002F After: fires on bfcache entry AND on real unloads; does not block bfcache.\naddEventListener('pagehide', () => navigator.sendBeacon('\u002Flog', JSON.stringify(pending)));\n\u002F\u002F trade-off: pagehide also fires when the page enters bfcache, so code that\n\u002F\u002F \"cleans up for good\" must be able to undo itself on pageshow if restored.\n","javascript","",[208,402,403,411,458,464,496,502],{"__ignoreMap":400},[404,405,407],"span",{"class":166,"line":406},1,[404,408,410],{"class":409},"sjfSM","\u002F\u002F Before\n",[404,412,414,418,422,426,429,433,436,439,441,444,446,450,452,455],{"class":166,"line":413},2,[404,415,417],{"class":416},"smZ65","addEventListener",[404,419,421],{"class":420},"saISM","(",[404,423,425],{"class":424},"sZ8jY","'unload'",[404,427,428],{"class":420},", () ",[404,430,432],{"class":431},"sPARh","=>",[404,434,435],{"class":420}," navigator.",[404,437,438],{"class":416},"sendBeacon",[404,440,421],{"class":420},[404,442,443],{"class":424},"'\u002Flog'",[404,445,233],{"class":420},[404,447,449],{"class":448},"sPXB4","JSON",[404,451,223],{"class":420},[404,453,454],{"class":416},"stringify",[404,456,457],{"class":420},"(pending)));\n",[404,459,461],{"class":166,"line":460},3,[404,462,463],{"class":409},"\u002F\u002F After: fires on bfcache entry AND on real unloads; does not block bfcache.\n",[404,465,467,469,471,474,476,478,480,482,484,486,488,490,492,494],{"class":166,"line":466},4,[404,468,417],{"class":416},[404,470,421],{"class":420},[404,472,473],{"class":424},"'pagehide'",[404,475,428],{"class":420},[404,477,432],{"class":431},[404,479,435],{"class":420},[404,481,438],{"class":416},[404,483,421],{"class":420},[404,485,443],{"class":424},[404,487,233],{"class":420},[404,489,449],{"class":448},[404,491,223],{"class":420},[404,493,454],{"class":416},[404,495,457],{"class":420},[404,497,499],{"class":166,"line":498},5,[404,500,501],{"class":409},"\u002F\u002F trade-off: pagehide also fires when the page enters bfcache, so code that\n",[404,503,505],{"class":166,"line":504},6,[404,506,507],{"class":409},"\u002F\u002F \"cleans up for good\" must be able to undo itself on pageshow if restored.\n",[15,509,510,511,223],{},"Expected outcome: the most common blocker disappears. Details in ",[19,512,514],{"href":513},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Freplacing-unload-handlers-for-bfcache\u002F","replacing unload handlers for bfcache",[390,516,518],{"id":517},"_2-close-connections-on-pagehide-reopen-on-pageshow","2. Close connections on pagehide, reopen on pageshow",[395,520,522],{"className":397,"code":521,"language":399,"meta":400,"style":400},"let socket = connect();\naddEventListener('pagehide', (e) => { if (e.persisted) socket.close(1000, 'bfcache'); });\naddEventListener('pageshow', (e) => { if (e.persisted) socket = connect(); });\n\u002F\u002F trade-off: messages sent while the page was frozen are missed. Fetch a delta\n\u002F\u002F (\"what changed since timestamp X\") when reconnecting.\n",[208,523,524,541,586,617,622],{"__ignoreMap":400},[404,525,526,529,532,535,538],{"class":166,"line":406},[404,527,528],{"class":431},"let",[404,530,531],{"class":420}," socket ",[404,533,534],{"class":431},"=",[404,536,537],{"class":416}," connect",[404,539,540],{"class":420},"();\n",[404,542,543,545,547,549,552,556,559,561,564,567,570,573,575,578,580,583],{"class":166,"line":413},[404,544,417],{"class":416},[404,546,421],{"class":420},[404,548,473],{"class":424},[404,550,551],{"class":420},", (",[404,553,555],{"class":554},"sQw3B","e",[404,557,558],{"class":420},") ",[404,560,432],{"class":431},[404,562,563],{"class":420}," { ",[404,565,566],{"class":431},"if",[404,568,569],{"class":420}," (e.persisted) socket.",[404,571,572],{"class":416},"close",[404,574,421],{"class":420},[404,576,577],{"class":448},"1000",[404,579,233],{"class":420},[404,581,582],{"class":424},"'bfcache'",[404,584,585],{"class":420},"); });\n",[404,587,588,590,592,595,597,599,601,603,605,607,610,612,614],{"class":166,"line":460},[404,589,417],{"class":416},[404,591,421],{"class":420},[404,593,594],{"class":424},"'pageshow'",[404,596,551],{"class":420},[404,598,555],{"class":554},[404,600,558],{"class":420},[404,602,432],{"class":431},[404,604,563],{"class":420},[404,606,566],{"class":431},[404,608,609],{"class":420}," (e.persisted) socket ",[404,611,534],{"class":431},[404,613,537],{"class":416},[404,615,616],{"class":420},"(); });\n",[404,618,619],{"class":166,"line":466},[404,620,621],{"class":409},"\u002F\u002F trade-off: messages sent while the page was frozen are missed. Fetch a delta\n",[404,623,624],{"class":166,"line":498},[404,625,626],{"class":409},"\u002F\u002F (\"what changed since timestamp X\") when reconnecting.\n",[15,628,629],{},"Expected outcome: pages with live data become eligible without losing updates.",[390,631,633],{"id":632},"_3-keep-indexeddb-transactions-short","3. Keep IndexedDB transactions short",[15,635,636,637,640],{},"Never hold a transaction open across ",[208,638,639],{},"await","s on network requests or user input; complete writes promptly so no transaction is pending when the user navigates away.",[390,642,644,645,648],{"id":643},"_4-narrow-no-store-to-pages-that-need-it","4. Narrow ",[208,646,647],{},"no-store"," to pages that need it",[15,650,651,652,655,656,658,659,223],{},"Use ",[208,653,654],{},"Cache-Control: no-cache, private"," for pages that must be revalidated but are not secret; reserve ",[208,657,647],{}," for genuinely sensitive content. See ",[19,660,662],{"href":661},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002F","Cache-Control no-store and bfcache",[390,664,666],{"id":665},"_5-deal-with-blocking-iframes","5. Deal with blocking iframes",[15,668,669],{},"Update vendors, lazy-load embeds so they are not present on pages users commonly navigate back to, or replace them with facades that create the iframe only on interaction.",[15,671,672],{},[35,673,42,676,42,679,42,682,42,684,42,687,42,689,42,694,42,701,42,705,42,709,42,712,42,716,42,720,42,723,42,725,42,728,42,730,42,733,42,736,42,740,42,742,42,745,42,747,42,750,42,753,42,757,42,759,42,762,42,764,42,766,42,770,42,774,42,778,42,780,42,784,42,786,42],{"viewBox":674,"width":38,"role":39,"ariaLabel":675,"style":41},"0 0 760 244","Common bfcache-blocking patterns paired with the replacement pattern that keeps the feature working.",[44,677],{"className":678,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,680,681],{},"Replacement APIs for blocking patterns",[55,683,675],{},[44,685],{"x":77,"y":77,"width":78,"height":686,"rx":80,"fill":81,"stroke":73,"style":82},"242",[84,688,681],{"x":86,"y":87,"fill":73,"style":88},[44,690],{"x":86,"y":91,"width":691,"height":692,"rx":48,"fill":73,"stroke":73,"style":693},"210.0","30.0","fill-opacity:0.06;stroke-opacity:0.4",[84,695,700],{"x":696,"y":697,"fill":73,"style":698,"textAnchor":699},"38.0","75.5","font-size:12.5px;font-weight:700","start","Blocking pattern",[44,702],{"x":703,"y":91,"width":704,"height":692,"rx":48,"fill":73,"stroke":73,"style":693},"238.0","247.0",[84,706,708],{"x":707,"y":697,"fill":73,"style":698,"textAnchor":102},"361.5","Replacement",[44,710],{"x":711,"y":91,"width":704,"height":692,"rx":48,"fill":73,"stroke":73,"style":693},"485.0",[84,713,715],{"x":714,"y":697,"fill":73,"style":698,"textAnchor":102},"608.5","Restore step",[44,717],{"x":86,"y":718,"width":691,"height":692,"rx":48,"fill":81,"stroke":73,"style":719},"86.0","stroke-opacity:0.35",[84,721,323],{"x":696,"y":722,"fill":73,"style":698,"textAnchor":699},"105.5",[44,724],{"x":703,"y":718,"width":704,"height":692,"rx":48,"fill":81,"stroke":73,"style":719},[84,726,727],{"x":707,"y":722,"fill":73,"style":107,"textAnchor":102},"pagehide \u002F visibilitychange",[44,729],{"x":711,"y":718,"width":704,"height":692,"rx":48,"fill":73,"stroke":73,"style":693},[84,731,732],{"x":714,"y":722,"fill":73,"style":107,"textAnchor":102},"none needed",[44,734],{"x":86,"y":735,"width":691,"height":692,"rx":48,"fill":81,"stroke":73,"style":719},"116.0",[84,737,739],{"x":696,"y":738,"fill":73,"style":698,"textAnchor":699},"135.5","Open WebSocket",[44,741],{"x":703,"y":735,"width":704,"height":692,"rx":48,"fill":81,"stroke":73,"style":719},[84,743,744],{"x":707,"y":738,"fill":73,"style":107,"textAnchor":102},"close on pagehide",[44,746],{"x":711,"y":735,"width":704,"height":692,"rx":48,"fill":95,"stroke":95,"style":96},[84,748,749],{"x":714,"y":738,"fill":73,"style":107,"textAnchor":102},"reconnect on pageshow",[44,751],{"x":86,"y":752,"width":691,"height":692,"rx":48,"fill":81,"stroke":73,"style":719},"146.0",[84,754,756],{"x":696,"y":755,"fill":73,"style":698,"textAnchor":699},"165.5","Long IndexedDB transaction",[44,758],{"x":703,"y":752,"width":704,"height":692,"rx":48,"fill":81,"stroke":73,"style":719},[84,760,761],{"x":707,"y":755,"fill":73,"style":107,"textAnchor":102},"commit promptly",[44,763],{"x":711,"y":752,"width":704,"height":692,"rx":48,"fill":73,"stroke":73,"style":693},[84,765,732],{"x":714,"y":755,"fill":73,"style":107,"textAnchor":102},[44,767],{"x":86,"y":768,"width":691,"height":769,"rx":48,"fill":81,"stroke":73,"style":719},"176.0","46.0",[84,771,773],{"x":696,"y":772,"fill":73,"style":698,"textAnchor":699},"195.5","Embed iframe holding",[84,775,777],{"x":696,"y":776,"fill":73,"style":698,"textAnchor":699},"211.5","connections",[44,779],{"x":703,"y":768,"width":704,"height":769,"rx":48,"fill":81,"stroke":73,"style":719},[84,781,783],{"x":707,"y":782,"fill":73,"style":107,"textAnchor":102},"203.5","facade on interaction",[44,785],{"x":711,"y":768,"width":704,"height":769,"rx":48,"fill":73,"stroke":73,"style":693},[84,787,788],{"x":714,"y":782,"fill":73,"style":107,"textAnchor":102},"re-create if needed",[187,790,792],{"id":791},"verification","Verification",[15,794,795],{},"Re-run the DevTools test for each template until it reports successful restoration. In the field, track the restoration rate and the distribution of remaining reasons weekly; it should climb as each fix ships and the remaining reasons should be ones outside your control. Add an end-to-end check for key templates so regressions are caught before release.",[187,797,799],{"id":798},"worked-example-removing-three-blockers-from-a-news-article","Worked Example: Removing Three Blockers from a News Article",[15,801,802,803,805,806,809,810,813],{},"A news article template had a 9% restoration rate. DevTools reported an ",[208,804,264],{}," handler (from a scroll-depth analytics script), an open WebSocket (live comment count) and a cross-origin iframe (a social embed). The analytics vendor offered a configuration flag to use ",[208,807,808],{},"visibilitychange","; the comment count socket was closed on ",[208,811,812],{},"pagehide"," and the count refreshed on restore; social embeds were replaced with a facade that loaded the iframe on click. Restoration rate rose to 81%, and back navigations from articles to section pages became instant for most users.",[187,815,817],{"id":816},"common-mistakes","Common Mistakes",[192,819,820,833,839,845],{},[195,821,822,42,830,832],{},[198,823,824,825,827,828,223],{},"Replacing ",[208,826,264],{}," with ",[208,829,239],{},[208,831,239],{}," is also problematic in some browsers and should only be added conditionally (for unsaved changes), then removed.",[195,834,835,838],{},[198,836,837],{},"Fixing only the DevTools reason."," Field data often shows different, user-specific blockers (logged-in widgets, consent-dependent vendors).",[195,840,841,844],{},[198,842,843],{},"Closing connections without reopening them."," Restored pages then show stale live data indefinitely.",[195,846,847,850],{},[198,848,849],{},"Assuming a fix in one template applies site-wide."," Each template has its own set of scripts and embeds.",[187,852,854],{"id":853},"edge-cases","Edge Cases",[15,856,857,860,861,863],{},[198,858,859],{},"Unload handlers added conditionally."," Some libraries add ",[208,862,264],{}," only in certain states (an unsaved form, an open modal). Test the states users are in when they navigate away, not just the default.",[15,865,866,869],{},[198,867,868],{},"Extensions."," Browser extensions can inject blockers. Field data will include some reasons you cannot reproduce; filter by frequency.",[15,871,872,875],{},[198,873,874],{},"Back navigation to a POST result."," Pages loaded via form POST have their own caching rules; prefer the POST-redirect-GET pattern so the page users return to is a cacheable GET.",[15,877,878,881,882,884],{},[198,879,880],{},"Mobile vs desktop."," Chromium on Android has historically been more lenient with ",[208,883,264],{}," than desktop; measure both platforms separately.",[187,886,888],{"id":887},"prioritising-fixes-across-a-large-site","Prioritising Fixes Across a Large Site",[15,890,891,892,894,895,897],{},"On a site with dozens of templates, blockers are not evenly distributed. Build a simple matrix: templates as rows (ordered by back\u002Fforward navigation volume, not total traffic), reasons as columns, and miss counts in the cells. Back\u002Fforward volume matters because templates users return to — listings, search results, feeds, category pages — benefit far more than terminal pages like checkout confirmation. Fix the cells with the largest counts on the highest-volume rows first. Shared blockers (a site-wide analytics ",[208,893,264],{}," handler, a global ",[208,896,647],{}," rule) usually dominate and are fixed once for every template; template-specific ones (a live widget on one page type) come next. Re-run the matrix after each release so the next fix is always chosen by data rather than by which blocker is easiest to understand.",[187,899,901],{"id":900},"faq","FAQ",[903,904,907,911],"details",{"className":905},[906],"faq-item",[908,909,910],"summary",{},"Which reasons are worth ignoring?",[15,912,913],{},"Those marked \"Not actionable\" in DevTools (browser limitations) and rare field reasons affecting a tiny share of misses. Focus on reasons that cover most misses on your highest-traffic templates.",[903,915,917,920],{"className":916},[906],[908,918,919],{},"Does an empty unload handler still block bfcache?",[15,921,922],{},"Yes. The presence of the listener is what matters, not what it does. Remove it entirely.",[903,924,926,929],{"className":925},[906],[908,927,928],{},"Can a Content Security Policy or other header block bfcache?",[15,930,931,932,934],{},"Most headers do not; ",[208,933,277],{}," is the notable exception. Some features enabled by headers, such as certain cross-origin isolation setups with specific APIs in use, can have their own restrictions, which DevTools will list.",[903,936,938,941],{"className":937},[906],[908,939,940],{},"How do I fix a blocker inside a third-party iframe?",[15,942,943],{},"You cannot change its code, so change how you use it: update to a newer vendor version, load it only after interaction, load it on fewer pages, or replace it. Report the issue to the vendor — many have fixed bfcache blockers after customer requests.",[903,945,947,950],{"className":946},[906],[908,948,949],{},"Will fixing blockers change my analytics numbers?",[15,951,952,953,955,956,827,958,960],{},"It can. Restored pages fire ",[208,954,214],{}," but not a new page load, so analytics that only count loads will under-count views. Most analytics libraries now handle ",[208,957,214],{},[208,959,218],{},"; verify yours does.",[187,962,964],{"id":963},"related","Related",[192,966,967,974,981],{},[195,968,969,973],{},[19,970,972],{"href":971},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fmeasuring-bfcache-hit-rate-in-rum\u002F","Measuring bfcache hit rate in RUM"," — tracking the effect of each fix.",[195,975,976,980],{},[19,977,979],{"href":978},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Frestoring-state-on-pageshow-after-bfcache\u002F","Restoring state on pageshow after bfcache"," — the other half of reconnecting.",[195,982,983,987],{},[19,984,986],{"href":985},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Freplacing-youtube-embeds-with-a-facade\u002F","Replacing YouTube embeds with a facade"," — a facade pattern that also helps bfcache.",[989,990,992],"script",{"type":991},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Fix bfcache Eligibility Blockers\",\n  \"description\": \"A systematic workflow for finding and fixing every reason your pages are not restored from the back\u002Fforward cache.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Replace unload with pagehide or visibilitychange\",\n      \"text\": \"Expected outcome: the most common blocker disappears.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Close connections on pagehide, reopen on pageshow\",\n      \"text\": \"Expected outcome: pages with live data become eligible without losing updates.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Keep IndexedDB transactions short\",\n      \"text\": \"Never hold a transaction open across awaits on network requests or user input; complete writes promptly so no transaction is pending when the user navigates away.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Narrow no-store to pages that need it\",\n      \"text\": \"Use Cache-Control: no-cache, private for pages that must be revalidated but are not secret; reserve no-store for genuinely sensitive content.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 5,\n      \"name\": \"Deal with blocking iframes\",\n      \"text\": \"Update vendors, lazy-load embeds so they are not present on pages users commonly navigate back to, or replace them with facades that create the iframe only on interaction.\"\n    }\n  ]\n}\n",[989,994,995],{"type":991},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Fix bfcache Eligibility Blockers\",\n  \"description\": \"A systematic workflow for finding and fixing every reason your pages are not restored from the back\u002Fforward cache.\",\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\u002Ffixing-bfcache-eligibility-blockers\u002F\"\n  }\n}\n",[989,997,998],{"type":991},"\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\": \"Fixing bfcache Eligibility Blockers\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers\u002F\"\n    }\n  ]\n}\n",[1000,1001,1002],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}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 .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}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 .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}",{"title":400,"searchDepth":413,"depth":413,"links":1004},[1005,1006,1007,1015,1016,1017,1018,1019,1020,1021],{"id":189,"depth":413,"text":190},{"id":255,"depth":413,"text":256},{"id":387,"depth":413,"text":388,"children":1008},[1009,1010,1011,1012,1014],{"id":392,"depth":460,"text":393},{"id":517,"depth":460,"text":518},{"id":632,"depth":460,"text":633},{"id":643,"depth":460,"text":1013},"4. Narrow no-store to pages that need it",{"id":665,"depth":460,"text":666},{"id":791,"depth":413,"text":792},{"id":798,"depth":413,"text":799},{"id":816,"depth":413,"text":817},{"id":853,"depth":413,"text":854},{"id":887,"depth":413,"text":888},{"id":900,"depth":413,"text":901},{"id":963,"depth":413,"text":964},"A systematic workflow for finding and fixing every reason your pages are not restored from the back\u002Fforward cache.","md",{"slug":1025,"type":1026,"breadcrumb":1027,"datePublished":1035,"dateModified":1035},"fixing-bfcache-eligibility-blockers","article",[1028,1031,1032,1033],{"name":1029,"url":1030},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1034},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers\u002F","2026-10-06",true,"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers",{"title":1039,"description":1040},"Fixing bfcache Eligibility Blockers Step by Step","Work through the reasons Chrome reports for back\u002Fforward cache misses — unload handlers, no-store, open connections, IndexedDB, iframes — and fix each one.","advanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Ffixing-bfcache-eligibility-blockers\u002Findex","aqU5fEgGcU9Wf0Qvyr-aE-83wykNJ9UqIdl8FnAUD5w",[1044,1047],{"title":662,"path":1045,"stem":1046},"\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache","advanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fcache-control-no-store-and-bfcache\u002Findex",{"title":1048,"path":1049,"stem":1050},"Measuring bfcache Hit Rate in RUM","\u002Fadvanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fmeasuring-bfcache-hit-rate-in-rum","advanced-caching-strategies-cdn-architecture\u002Fback-forward-cache-bfcache\u002Fmeasuring-bfcache-hit-rate-in-rum\u002Findex",1791308077737]