# Had an issue with bfcache

> Learn how the browser bfcache served a stale htmx counter in Chrome on back and forward, and how I fixed it with no-cache, no-store meta tags and headers.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2024-01-04 | Topics: [HTML](https://flaviocopes.com/tags/html/), [Web Platform](https://flaviocopes.com/tags/platform/) | Canonical: https://flaviocopes.com/bfcache-issue/

Today I learned about **bfcache** when someone pointed out a problem on an example I did of a counter in htmx.

You load the page, counter (whose state is stored on the server) is at 0.

Increment counter, 1, 2, 3. Increment happens without a full page reload.

Go back to a previous page in your browser with the back button, then go forward again to the counter.

Counter is at 0 again.

Not because it reset, but because the browser cached the first full page load in its bfcache (back/forward cache).

You need to refresh the page to see the actual count value.

This only happened in Chrome (and Chrome-based browsers like Arc). Safari? No problem. Firefox? No problem. And also, Chrome with DevTools open with “Cache disabled” setting? No problem (that’s why I didn’t notice).

Solution?

I added these meta tags to my HTML head tag:

```html
<meta http-equiv="Cache-Control" content="no-cache, no-store" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
```

I could also set them as HTTP headers, for example using [Astro](https://flaviocopes.com/astro-introduction/):

```javascript
import { defineConfig } from 'astro/config'
import node from '@astrojs/node'

export default defineConfig({
  output: 'server',
  adapter: node({
    mode: 'standalone',
  }),
  server: {
    headers: {
      'Cache-Control': 'no-cache, no-store',
      Pragma: 'no-cache',
      Expires: '0',
    },
  },
})
```

I had a hard time testing this because I couldn’t find a good way to clear the bfcache, until I had the idea of testing in incognito mode, and I was able to see it worked fine.

Read more about bfcache: [https://web.dev/articles/bfcache](https://web.dev/articles/bfcache)

Note that they suggest using

```javascript
window.addEventListener('pageshow', (event) => {
  if (event.persisted) {
    console.log('This page was restored from the bfcache.')
  } else {
    console.log('This page was loaded normally.')
  }
})
```

to detect a page was restored but this didn’t work at all, persisted is always false and this might be a bug.

Actually [it is a bug in Chrome](https://bugs.chromium.org/p/chromium/issues/detail?id=344507&can=5&colspec=ID%20Pri%20M%20Iteration%20ReleaseBlock%20Cr%20Status%20Owner%20Summary%20OS%20Modified) since 2014 🥲

If the no-cache no-store header is not an option, one snippet I found on StackOverflow to reload the page if page was detected to be from the bfcache, taking into consideration Chrome’s “bug”:

```javascript
window.addEventListener(
  'pageshow',
  function (event) {
    if (
      event.persisted ||
      performance.getEntriesByType('navigation')[0].type === 'back_forward'
    ) {
      location.reload()
    }
  },
  false,
)
```

…not optimal, of course.

But interesting.

Never heard of bfcache before.
