← Back to blog

Why You Still Can't See the Changes We Already Published on Your Site

Daniel García·

Ilustración del artículo: Why You Still Can't See the Changes We Already Published on Your Site

Last Thursday a client who runs an online language academy called me, more than a little annoyed, saying he’d been asking us for three days to change the price of a course on the site and it still showed the old number. I asked him to hit Ctrl+Shift+R in his browser. He saw it update instantly. He hung up without saying thanks, which I get.

If you’re not seeing changes on your site right after we publish them, it’s almost always a caching issue: your browser, an intermediate proxy, or our own server is serving a stored copy of the page that doesn’t yet know a newer version exists. The change has been sitting on the server since second one — nobody between the server and the screen has bothered to ask for it again.

There are really two different caches tangled up in that, and people mix them up for a good reason: from the outside they behave the same way, the site just “doesn’t change.” There’s the cache in each visitor’s browser, which we don’t fully control but can tell how long to trust a given file. And there’s the cache our own server serves before a request even reaches the page-generation step, which is entirely on us.

Hashed files never give us trouble

When Astro builds the site, it stamps a content hash into the filename of every CSS and JS file, something like index.a3f9c2.css. Change a single comma in the CSS and the hash changes, the filename changes, and the browser fetches a fresh copy without anyone telling it to. For those files we tell browsers to hang onto them for a full year (Cache-Control: public, max-age=31536000, immutable), and nothing goes wrong, because if the content changes, so does the name. That trick saved us a fair number of phone calls back when we set it up a couple of years ago.

The real problem sits in the HTML, which carries no hash in its name: it’s /pricing/index.html no matter how much the CSS it loads has changed underneath it. If we tell the browser or our nginx to cache that for, say, an hour, any price change takes up to an hour to show even though the server has had it ready since second one. And an hour is a long time when the person calling has a course that’s half-sold.

What we changed after one call too many

After a few calls like the one from the language academy, we stopped serving HTML with a long cache lifetime. Now it goes out with no-cache, must-revalidate: the browser has to ask the server whether anything’s new every single time, even though it still keeps a local copy so it doesn’t re-download the whole page when nothing changed. Hashed files stay cached for a year. That’s the combination running on the same VPS we wrote about recently, with nginx serving static assets in front of Docker — the very server we later put through a security audit that left us noticeably less at ease than we’d expected.

There’s still one case we haven’t quite solved.

When the change is an image with no hash in its name (a logo, a product photo a client sends us that keeps the same filename every time), we still fall back on the old advice, not proudly: hard-refresh or wait it out. We could hash those images too, but it would complicate the workflow for clients who upload their own photos over FTP, and for now the cost isn’t worth the benefit.

What we have learned is not to assume “published” means “visible.” When we ship an urgent change, we warn the client before they call, tell them it might take a minute to show up and why. It costs us thirty seconds to explain and saves us a call that starts with “this isn’t working” when it actually is — their browser just hasn’t heard about it yet.

cachinghostingdeploymentperformance