Enabling bfcache for Cache-Control: no-store

Chrome is making a change to allow back/forward cache (bfcache) usage for pages using Cache-Control: no-store when this is safe to do. Find out what that means for developers.

Background

Setting Cache-Control: no-store as an HTTP Header is a signal that the page shouldn't be stored in the HTTP cache. This should be used for pages containing sensitive data—for example, for pages when a user is logged in—but the no-store directive is often used on pages without sensitive data.

With bfcache, instead of destroying a page when the user navigates away, we postpone destruction and pause JS execution. If the user navigates back soon, we make the page visible again and unpause JS execution. This results in a near instant page navigation for the user.

While it is not required by the HTML spec, browsers typically take Cache-Control: no-store as a signal to avoid placing the page in bfcache. This is the largest reason the bfcache is not used, for about 17% of history navigations on mobile and 7% of history navigations on desktop. This means these pages don't benefit from the quick restores and must fully reload the page, including any network calls, JavaScript execution, and rendering.

Often Cache-Control: no-store is set to avoid caching issues when the site changes, but this reason is less relevant when the bfcache is used, as the full page is restored almost as if it had been left open all along.

How Chrome is changing this behavior

Chrome has announced an intention to change this behavior but is taking a cautious approach to this change. We have been running experiments since Chrome 116 and until recently these were running on 5% of page loads.

We increased this to 10% of page loads on October 2nd and intend to increase this further to 20% of page loads in November, 50% early next year, launching this fully shortly thereafter, with certain opt outs discussed next.

Sensitive data

While our analysis shows the majority of back or forward navigations don't include sensitive data and so should be eligible for the bfcache, there are cases where pages shouldn't be placed in the bfcache. For example on logging out, it shouldn't be possible to retrieve a logged in page by navigating back or forth.

To avoid this, Chrome will evict a page from the bfcache on changes to cookies, or other authorization methods.

In addition, use of the following APIs for pages using Cache-Control: no-store will continue to make those pages ineligible for bfcache:

Note that this is not a comprehensive list of APIs which prevent bfcache usage but the APIs that block bfcache on Cache-Control: no-store pages even if they are not being used at the time of leaving the page.

The bfcache timeout for Cache-Control: no-store pages is also reduced to 3 minutes (from 10 minutes used for pages which don't use Cache-Control: no-store) to further reduce risk.

Enterprise out opts

Enterprises often have difficult-to-update software and shared devices. The AllowBackForwardCacheForCacheControlNoStorePageEnabled policy can be disabled to continue to prevent bfcache usage for Cache-Control: no-store pages.

Testing the change

Developers can test this change with the following flag:

--enable-features=CacheControlNoStoreEnterBackForwardCache:level/restore-unless-cookie-change

If any of the previous exceptions apply—for example, cookies changing—this will prevent the page from using the bfcache with a reason of "Pages whose main resource has Cache-Control: no-store cannot enter back/forward cache." showing in the Chrome DevTools bfcache tester.

You can use this bfcache test page to test with and without this flag.

What developers should know

While developers won't need to make any changes for their users to benefit from this greater bfcache usage, there are some things that they may need to consider as a result of this. These were similar considerations that other sites may have experienced in the initial launch of bfcache in December 2021.

Impact on performance

The reason we are making this change is to improve the page experience for users on the web. We saw noticeable improvements to Core Web Vitals when we first launched bfcache, and now we want to bring those same improvements to more sites.

Site owners may see an improvement to their Core Web Vitals as this rolls out, and can measure bfcache usage in CrUX, including in the CrUX Dashboard.

Impact analytics

Pages restored from the bfcache "restore" the old page (including the JavaScript heap) rather than reload the page. Many popular analytics providers don't measure bfcache restores as new page views since they only trigger page views when they are initially loaded.

Sites may therefore see a reduction in page loads in their analytics when they start using the bfcache for the first time. We recommend considering these as pageviews, by setting listeners for the pageshow event and checking the persisted property:

// Send a pageview when the page is first loaded.
gtag('event', 'page_view');

// Send another pageview if the page is restored from bfcache.
window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    // Page was restored from bfcache, sent another page view.
    gtag('event', 'page_view');
  }
});

Handle updates on page restore

As sites may now see bfcache usage when they did not see this before and when the page would instead be fully reloaded with fresh data, developers may want to consider refreshing data on a bfcache restore.

Updates can be triggered in a similar manner to logging additional page views for analytics using the pageshow event and checking the persisted property.

Note that not all content needs to be updated and users may prefer going "back" to the content they saw previously. For example, refreshing a list of articles may mean the user no longer sees an article they were going back to view.

Impact on advertisements

Similar to analytics impact, sites may see a reduction in ad impressions if ads only load on page load. Ads can be programmatically refreshed on bfcache restore to ensure parity with full page loads, again using the pageshow event and checking the persisted property but may not always be the right thing to do. Refer to your ad provider's documentation on how to trigger ad reloads.

More information on bfcache

For more information on bfcache, see our comprehensive bfcache technical guide.

Feedback

We are eager to hear feedback on this change which can be provided in Chrome's issue tracker using the bfcache component.

Conclusion

We are excited to bring the benefit of bfcache to many more pages to improve page experience for users. We have carefully considered this change and our approach seeks to roll this out in as safe a manner as possible. We hope the information provided here will help developers understand this change and make any changes necessary to avoid issues when this happens.