Making Your Pages Eligible for Chrome's Back/Forward Cache
Chrome's bfcache can restore pages instantly, but common scripts and APIs quietly block eligibility. This post walks through the blockers, a DevTools diagnostic workflow, and a code pattern to keep your nav fast.
19 Feb 2026, 14:05 UTC

How bfcache Works
When you navigate away from a page, Chrome may keep a fully frozen snapshot of the DOM, JavaScript heap, and pending timers in memory. Pressing Back restores that snapshot instantly, skipping a full fetch and render. This is the back/forward cache, or bfcache, and it can make navigation feel instantaneous. The feature has been part of Chrome for years, but many pages are silently excluded from it, and developers only notice when a user reports a slow Back navigation.
Common Blockers
- Open IndexedDB connections or transactions prevent bfcache eligibility.
- In-flight fetch or XMLHttpRequest requests that have not yet resolve block the cache.
- Active WebSocket or WebRTC connections keep the page state live and ineligible.
- Cache-Control: no-store has been relaxed for some non-sensitive pages, but eligibility still depends on the Chrome release your users run.
- Unload event listeners historically disqualified a page; Chrome now heuristically ignores many, but using pagehide or visibilitychange is the safer approach.
Diagnose with Chrome DevTools
Chrome DevTools provides a dedicated bfcache diagnostic page.
- Open Chrome DevTools (F12 on Windows or Cmd+Option+I on macOS).
- Go to the Application panel.
- In the left sidebar, select Back/forward Cache.
- Click the Test back/forward cache button.
- Read the listed blocking reasons, if any, or a confirmation that your page is eligible.
No elevated permissions are required beyond DevTools access. This is a read-only diagnostic; it does not alter page state or tab data. If the test lists reasons, those are the exact factors currently preventing eligibility on the Chrome version running the browser.
// Minimal pageshow listener to detect bfcache restore
window.addEventListener('pageshow', (event) => { if (event.persisted) { // Page was restored from bfcache // Refresh widgets, reset timers, or re-authenticate as needed } });Because the pageshow event only fires once when the document becomes visible, placing this check early ensures that subsequent interactions such as button clicks or timer updates are not mistaken for a fresh load.
Code Pattern for Persisted Restores
The pageshow event's persisted property is the standard way to know when a page has been restored from bfcache. Because a restored page does not re-run its initial scripts, any analytics tracking or widget initialization that relies on a fresh page load must hook into this signal. For example, if your site counts pageviews on load, attaching a listener with the persisted guard prevents undercounting restores:
// Analytics that works across normal loads and bfcache restores
window.addEventListener('pageshow', (event) => { if (event.persisted) { // This is a bfcache restore; skip the normal pageview hit return; } // Normal load send the pageview sendPageview(); });Trade-offs and Limitations
bfcache is an in-memory, per-tab feature. It is not a substitute for HTTP caching or service workers, and memory pressure can evict entries. Pages handling sensitive data should deliberately opt out using Cache-Control: no-store rather than risk restoring stale authenticated state. Additionally, bfcache eligibility rules and heuristics have changed across Chrome releases; a page that is eligible on Chrome 120 might be blocked on an older or newer version. Always verify on the Chrome version your actual users run.
Actionable Closing
- Run the DevTools bfcache test on a representative page and note any blocking reasons.
- Close or defer open IndexedDB transactions, finish in-flight fetches, and terminate WebSocket/WebRTC connections before the user navigates away.
- Replace any unload listeners with pagehide or visibilitychange handlers.
- Add a pageshow listener that checks event.persisted and adjusts analytics or widget state accordingly.
- Re-run the DevTools test to confirm eligibility, then monitor real-world navigation timing to quantify the latency win.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.