Ask
23

Deployed a new version and some visitors still see the old site for days — how do I force them onto the new one?

Static site. Deployed changes, checked in a private window and it looked right, then had three people tell me they were still seeing the previous version. One of them was still on it four days later.

Hard refresh fixes it for them, but I cannot ask every visitor to do that.

What I want to understand:

  1. Where is the old copy actually being kept? There seem to be several possible places.
  2. Why does it persist for days when I never set anything like that?
  3. What is the correct way to structure this so it stops being a problem on every deploy?
5 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @fare_class_fay · 2h ago

    On question 2: you did set something, in the sense that not setting anything is itself a choice.

    With no Cache-Control header, browsers apply heuristic caching — they guess a lifetime, commonly from the Last-Modified date, often around 10% of the file's age. A file that has been unchanged for a year gets guessed a long life. So the longer a site sits stable, the longer stale copies persist after you finally change it, which is exactly backwards from what anyone wants and is why it feels arbitrary.

    That is also why it varies by visitor: they each cached at different times, so they each got a different guess.

    The lesson is that silence is not neutral. Every response should say what it wants, explicitly.

    24
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @form_field_faruk · 2d ago · 2 replies

    There are usually four copies and you have to know which one is biting you, because the fixes are different and only one of them is under your direct control.

    1. The browser cache. The visitor's own disk. You cannot clear it remotely. You can only influence it with the headers you sent last time — which is the trap, because the headers that are causing the problem are the ones on the old file, already delivered.
    2. A CDN or proxy. Your edge network holds a copy. This one you can purge, and most deploy tools do.
    3. An intermediate cache — a corporate proxy, an ISP appliance. Rare now that nearly everything is HTTPS, but it exists.
    4. A service worker, if you have ever had one. This is the four-day person almost every time. A service worker serves from its own cache and can keep doing so indefinitely, entirely ignoring your headers and your CDN purge.

    Start by asking the stuck person to open developer tools and check for a registered service worker. If there is one, that is your answer and nothing else you do will help.

    27
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @cache_bust_cato · 3d ago

      There was a service worker, from a framework default about two years ago that I had forgotten was ever enabled. That is almost certainly the four-day case.

      12
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @push_payment_pia · 23h ago

    The structural fix, which makes this a non-issue forever, is content hashing plus two cache policies:

    • Assets — JS, CSS, images — get a hash in the filename: app.9f2c1a.js. Serve them with Cache-Control: public, max-age=31536000, immutable. They can be cached forever because a changed file is a different name. Nothing is ever stale, because nothing is ever overwritten.
    • HTML — the entry point — gets Cache-Control: no-cache. Not no-store; no-cache means "you may keep it, but revalidate before using it". So the browser checks in, and gets the new HTML, which references the new hashed asset names.

    That is the entire pattern. The HTML is small and revalidating it is cheap, and it is the only thing that ever needs to be fresh, because it names everything else.

    Every modern build tool does the hashing part for you. The part people miss is the header on the HTML.

    22
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @token_leak_tomas · 4h ago

    For the people who are already stuck — because the fix above only helps from the next deploy onward — the service worker case has a specific escape.

    If you no longer want one, deploy a service worker file that unregisters itself and clears its caches, rather than deleting the file. Deleting it does nothing: browsers that already have it registered keep running the old one and never ask for a file that is not there.

    A few lines that call registration.unregister() and delete the cache keys, shipped once, cleans up the installed base. Then remove it a few months later.

    Unpleasant, and the only thing that works.

    13
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report