Skip to content

Glossary bfcache (back/forward cache)

What is bfcache?

Definition

The bfcache (back/forward cache) is a browser feature that keeps a full page in memory when you leave it, so that navigating back or forward restores it instantly, without new requests to the server.

On this page 5
  1. What bfcache means
  2. How it works
  3. Why it matters
  4. Buenas prácticas
  5. Errores frecuentes
In brief

It is a browser memory that saves a full page when leaving it, so it can be restored instantly if the user navigates back.

What bfcache means

The bfcache is an optimization that belongs to the browser, not to your server or your code. When someone leaves a page by clicking a link or typing a new URL, the browser doesn't necessarily destroy that tab: it can pause JavaScript execution and keep the document's entire state in RAM. If that person comes back later using the back or forward button, the browser restores the page exactly as it was, without downloading a single resource again.

Google estimates that one in ten navigations on desktop and one in five on mobile are of this type, going back or forward. It's a proportion that rarely gets measured, because auditing tools tend to focus only on a page's first load, the one that feeds most Core Web Vitals reports. Anyone who only measures that first load misses this entire slice of what real users actually experience.

The bfcache shouldn't be confused with other forms of caching. The HTTP cache stores individual files, such as images, stylesheets, or scripts, so they don't have to be downloaded again. The bfcache stores the entire page, including its JavaScript state, ready to reappear without executing anything from scratch. That's why a page with bfcache active feels instant when you go back, while a full reload, even a well optimized one, always involves at least one network request.

How it works

The browser decides whether a page is eligible for the bfcache the moment the user leaves it, based on a list of technical conditions. If the page meets them, the rendering process gets frozen in memory instead of being destroyed. JavaScript execution stops, timers stop running, and the page waits there, untouched, until the user returns or until the browser needs to free that memory for something else. From the server's point of view, nothing happens at all, not a single log entry gets created for that visit.

There are factors that prevent this freeze, and web.dev documents them precisely. The most decisive one is an unload event handler: any page that still uses that event to run code gets excluded from the bfcache in Chrome and Firefox, without exception. A Cache-Control: no-store header on the server's response produces the same effect, because it explicitly tells the browser not to retain anything from that page. Open connections left running when the page is left also block the bfcache, such as an ongoing IndexedDB transaction, an unresolved fetch or XMLHttpRequest request, an active WebSocket, or a WebRTC connection, as well as any window.opener reference that keeps the original tab linked to the new one.

To find out whether a specific page qualifies for the bfcache or not, Chrome DevTools includes a dedicated test in the Application tab, under Back-forward cache, which runs the actual check and returns the exact reason for a block when there is one, concrete enough to hand straight to a developer. Another way to measure it is programmatic: the Navigation Timing API exposes the navigation type through performance.getEntriesByType('navigation')[0].type, with the value back_forward when the page came from the bfcache, which lets you track this proportion in any analytics system of your own.

Why it matters

The bfcache doesn't change a single line of a page's content, but it completely changes how its speed is perceived for a far from small share of visits: between one in ten and one in five navigations, according to the figures cited in the previous section. When a page is restored from the bfcache, its LCP and FCP values practically match the moment of restoration, because there's no download or rendering from scratch. Running the Back-forward cache test in Chrome DevTools is often enough to confirm this connection in a few minutes.

This explains a pattern that confuses anyone auditing performance without knowing about the bfcache: a website that apparently hasn't changed anything improves its speed metrics from one day to the next, or worsens them after a deployment that, unnoticed, introduced an unload handler or a no-store header. The cause isn't in the visible code, it's in whether that page remains eligible for the bfcache or has stopped being so.

For a team that depends on perceived performance, such as a store with navigation from catalog to product and back, or a publisher with article listings, the bfcache isn't a minor technical detail. It's the difference between going back feeling instant or feeling like another load, and that difference shows up in every session that includes at least one backward navigation, which is to say, a good share of all user behavior on the site.

Buenas prácticas

  • Remove any unload event handler and replace it with pagehide or visibilitychange, which are compatible with the bfcache.
  • Check that no HTML response carries Cache-Control: no-store unless the page actually contains sensitive data that shouldn't persist in memory.
  • Close open connections, such as WebSocket, WebRTC, or pending fetch requests, in the pagehide event, instead of leaving them active when the page is left.
  • Test every important template with Chrome DevTools' Back-forward cache test, not just the homepage.
  • Avoid leaving window.opener accessible when opening links in a new tab; add rel="noopener" to those links.
  • Measure the actual proportion of back_forward navigations on your site with the Navigation Timing API before assuming the problem is marginal.

Errores frecuentes

  • Assuming the perceived slowness when going back is a server problem, when the block is in the client-side code itself.
  • Adding Cache-Control: no-store to ordinary pages out of caution, without measuring whether they truly contain data that shouldn't be stored.
  • Leaving an unload handler inherited from an old analytics script that nobody has reviewed since it was installed.
  • Confusing the HTTP cache for individual files with the bfcache for the whole page, and assuming optimizing one already covers the other.
Manuel Riveiro Rodriguez CEO & Digital Strategist

A technical audit covers this and everything else in one pass.

Request an audit

Frequently asked

Does the bfcache affect SEO?

It isn't a ranking factor Google has ever declared outright, but it does influence the speed metrics Google collects as real-user field data. A page eligible for the bfcache improves the actual experience of someone navigating back, and that experience is exactly what Core Web Vitals metrics are trying to capture.

How do I know if my site is eligible for the bfcache?

With Chrome DevTools: open the Application tab, go to Back-forward cache, and click Run Test. The tool navigates away and back on its own, and if something prevents caching, it shows the exact reason instead of a generic eligible or not eligible result.

Does the bfcache store sensitive data on the user's device?

It stores the page in RAM, not on disk, and only for as long as the tab or the browser process stays open; once that closes, the copy is gone for good. Even so, for pages with sensitive information it's worth using Cache-Control: no-store deliberately, not out of general habit.

Do all browsers have a bfcache?

Chrome, Firefox, and Safari all implement it, though with noticeable differences in which conditions block it in practice. An unload handler disables it in Chrome and Firefox without exception; it's worth checking the actual behavior in each engine rather than assuming it's identical.

Why did my LCP suddenly improve without any code changing?

It's a typical sign of the bfcache: if a larger share of navigations is now restored from memory instead of loading from scratch, the average LCP drops even though nothing in the page's visible code has changed at all, since each restore counts as an almost instant navigation.