Cache busting: when your update does not show up

You uploaded the fix and you see it. Everyone else sees the old version for hours, because their browsers were told to keep it. Cache busting changes the file's address when the file changes, so the old copy is never asked for. A document at one address has no file to bust.

Cache busting is the practice of changing a file's address whenever its contents change, so that browsers and intermediate caches that kept the old copy have no reason to reuse it.

The markup. The highlighted line is the part this term is about.
The markup. The highlighted line is the part this term is about.

It exists because caching works: a stylesheet served with a long lifetime is kept for hours or days, which makes pages fast and makes the person who just uploaded a fix the only one who can see it.

This guide covers where copies are held, the two headers that control them, the version and hash techniques, and why a page served as a document rather than a file does not have the problem.

You fixed a number, republished, and three people still see the old figure. Nothing is broken — a cached copy is being served.

Where the cached copies are held

Layer Cleared by
The reader's browser A hard reload, or expiry
A content delivery network A purge you request, or expiry
A corporate proxy Its own policy — not by you
A service worker Its own update logic
Cache busting is changing a file's address whenever the file changes, so browsers that kept the old copy fetch the new one. It is why the person who uploaded the fix sees it and everyone else sees the old version for hours.
Cache busting is changing a file's address whenever the file changes, so browsers that kept the old copy fetch the new one. It is why the person who uploaded the fix sees it and everyone else sees the old version for hours.

You control the first two at best. Hence the strategy below: rather than trying to clear caches, make the new content live at an address that has never been cached.

A copy per person ✗ Each edit lives on one machine ✗ No way to merge the changes ✗ Nobody can say which is current ✗ The oldest copy keeps circulating One address ✓ Everyone opens the same page ✓ A correction is seen by all ✓ There is only one current version ✓ Forwarding shares the page, not a copy
A cached copy per reader, each as old as its last fetch, versus one page served fresh on every open.

The two headers

Cache-Control: public, max-age=31536000, immutable

"Keep this for a year and do not ask again." Correct for a file whose address changes when its contents change.

Cache-Control: no-cache

Misleadingly named: it means "you may store it, but check with me before reusing it". Correct for an HTML page. The one that means never store is no-store, which you rarely want.

The standard arrangement

report.html          Cache-Control: no-cache
styles.a3f9c.css     Cache-Control: public, max-age=31536000, immutable
chart.8b21d.js       Cache-Control: public, max-age=31536000, immutable
logo.5c7e0.png       Cache-Control: public, max-age=31536000, immutable

The HTML is always checked; everything it points at is cached forever. When the CSS changes, its hash changes, so the HTML now points at a new address — which has no cached copy and is fetched. No purging, no waiting.

This is why build tools put hashes in filenames. It is the whole mechanism.

Without a build step

<link rel="stylesheet" href="/styles.css?v=12">
<script src="/chart.js?v=12"></script>

A version query is a different address as far as caches are concerned. Bump the number when you change the file. Manual, and it works.

Do not use a timestamp or a random value:

<!-- defeats caching entirely -->
<link rel="stylesheet" href="/styles.css?v=1757712000000">

That is a new address on every page load, so the file is re-downloaded every time and the cache is useless.

Favicons are the worst case

Favicons are cached more aggressively than anything else, sometimes surviving a hard reload. A version query is usually the only thing that works:

<link rel="icon" href="/icon.svg?v=3" type="image/svg+xml">

Why "hard reload" is not an answer

It works for you and tells you nothing about your readers, who will not do it and often cannot be asked to. It also may not clear a delivery network or a corporate proxy.

If your answer to a stale page is "tell them to hard reload", the caching setup needs fixing.

A single self-contained page

A self-contained page has one address and no assets, so there is nothing to version. With no-cache on the HTML, an update is visible immediately.

That simplicity is a genuine argument for single-file documents: the entire class of problem on this page does not exist.

Which is also why publishing beats re-uploading

The static-host cycle — edit locally, re-upload, wait for the cache — has this problem built in. A page whose content is edited in place at a stable address does not: the address never changes, and the content served from it is current.

In NOS an edit is visible at the same address without a re-upload, so "did they get the new version" stops being a question you have to ask.

The three places a copy can be

The reader's browser keeps a copy for as long as the response's max-age allows. A content delivery network in front of the host keeps its own copy, with its own rules, and serves it to every reader in a region.

A proxy at a company's edge may keep a third. A change has to get past all three, and changing the address is the only method that works on all of them at once, because none of them has ever seen the new address before.

Why "just refresh" does not fix it for anyone else

A hard refresh forces the reader's own browser to fetch again; it does nothing for the delivery network's copy or for anyone else's browser.

That is why the person who uploaded the fix can see it after a refresh and confidently tell everyone else it is live. Test from a browser that has never opened the page, or from a phone on a different network, before announcing an update.

Making updates show up: 4 steps

  1. Give changing files a version in their address. styles.css?v=2026-09-15, or a hash in the file name. Change it whenever the file changes.
  2. Let those files be cached for a long time. Cache-Control: max-age of a year with immutable. Safe, because a change means a new address.
  3. Tell browsers to revalidate the page itself. Cache-Control: no-cache on the HTML, so the page is checked on every open and its links point at the current versions.
  4. For a document people edit, do not host it as a file at all. A NOS page is served from the document and is current on every open; the static host comparison is this point in full.

Questions people ask

Why do readers see the old version after I update a file?

A cached copy is still within its lifetime, so the browser or an intermediate cache serves it without asking whether anything changed.

What is the reliable fix?

Change the address, not the file — styles.a3f9c.css or styles.css?v=12. A new address has no cached copy, so the new content is fetched.

Does a hard reload help?

For you, yes. It does nothing for your readers, who will not perform one, and it may not clear intermediate caches.

What should the HTML page itself be cached as?

Briefly, or revalidated every time. The HTML is what points at the versioned assets, so if it is stale nothing else can update.

Keep reading