BE AWESOME
Settings
Dev Notes
📅 September 10, 2026 · ⏱️ 5 min read

The Cache-Busting Bug That Cost Every Visitor Bandwidth for Months

Random query strings were busting the cache on every single request instead of only when a deploy actually shipped something new.

This post is about The Cache-Busting Bug That Cost Every Visitor Bandwidth for Months
Check the Status Page →

Every CSS and JS file on the site was getting a random cache-busting query string appended on every single request, which sounds harmless and was actually quietly defeating the entire point of browser caching for every visitor, on every page load, since the site went live. Today that gets replaced with a stable version tied to each deploy instead.

Random cache-busting was solving the wrong problem the wrong way

Cache-busting query strings exist to solve a real problem: after deploying updated CSS or JS, you need browsers to fetch the new version instead of serving a stale cached copy from before the update. A random string on every request does solve that, but at a real cost — it also busts the cache for visitors who haven't changed anything at all, forcing every browser to re-download every stylesheet and script on every single page load, indefinitely, deploy or no deploy. That's a meaningful amount of unnecessary bandwidth and load time paid on every single request, in exchange for solving a problem that only actually needs solving once per deploy, not once per page load.

A deploy-tied version number solves the actual problem, not a proxy for it

Tying the cache-busting value to something that only changes when a deploy actually happens — rather than something that changes on every request regardless of whether anything changed — means a browser can finally cache CSS and JS long-term the way caching is supposed to work. The file only appears "new" to a browser when it's genuinely new, immediately after a real deploy ships updated code, and stays recognized as unchanged, safely servable from cache, for every request in between deploys. That's a much more precise match between the cache-busting mechanism and the actual problem it's meant to solve, instead of a blunt instrument that happens to solve it as an accidental side effect of being wasteful on every single request.

Choosing what the version value actually is mattered

The version value needed to be something that reliably changes exactly when a deploy ships new code, and nothing more often than that. A timestamp tied to actual deploy time fits that requirement cleanly — it changes precisely once per deploy, in a way that's automatic and requires no manual bookkeeping on my part to keep synchronized. I didn't want a value I'd have to remember to bump by hand with every release, since a manual step like that is exactly the kind of thing that eventually gets forgotten under time pressure, silently reintroducing the stale-cache problem this whole change exists to prevent.

Mobile connections feel this kind of waste more than desktop ones do

Re-downloading every stylesheet and script on every page load is annoying but largely invisible on a fast desktop connection with effectively unlimited data. It's a meaningfully worse experience on a slower or metered mobile connection, where every unnecessary re-download is both slower to complete and potentially costing someone real data allowance for files that hadn't actually changed since their last visit. Given how much of this site's traffic plays on mobile, fixing wasteful caching behavior isn't just a nice efficiency improvement in the abstract — it's specifically improving the experience for exactly the visitors least equipped to absorb the cost of it being wrong.

Testing a caching fix means actually verifying caching, not just checking pages still load

Confirming this actually worked meant more than checking that pages still rendered correctly, which they would even if caching were completely broken. I had to verify browser dev tools actually showed cached responses being served on repeat visits between deploys, and separately confirm a real deploy correctly busted that cache and served fresh files afterward. Those are two different failure modes to check for — caching too aggressively, so an update never reaches returning visitors, and not caching at all, keeping the exact wasteful behavior this change was supposed to fix. Getting both directions right needed actually inspecting network behavior directly, not just eyeballing whether the site looked fine.

This also matters more now than it would have back in March

The cost of unnecessary re-downloads scales with how much CSS and JS a page actually loads, and the site has grown considerably since launch — a shared game shell, an expanded web tools suite, achievements, leaderboards, all adding real script and style weight that a March-era version of the site simply didn't carry yet. The random cache-busting approach was always wasteful, but it was a smaller waste back when there was less to re-download on every request. Fixing it today, once the site has meaningfully more static assets than it used to, has a proportionally bigger payoff than fixing the exact same underlying issue would have delivered six months ago.

Why this had been sitting untouched for months

I'll be honest that this is the kind of fix that's easy to keep deprioritizing indefinitely — it doesn't produce a new feature, a new game, or anything visible to point at, and the site worked "fine" the whole time this was live, in the sense that nothing was visibly broken. It just quietly cost every single visitor more bandwidth and load time than necessary, for months, in a way nobody would ever notice or complain about directly. That's exactly the kind of invisible inefficiency that's tempting to leave alone forever, and I'm glad I finally carved out the time to fix it properly instead of letting it become permanent by default.

This is one of those changes where the entire success metric is something quietly getting faster and cheaper for every visitor, without a single new pixel on screen to show for it. I'll take that trade every time it's available, even knowing this exact kind of fix is the least likely of anything I build to ever get mentioned by anyone actually using the site, precisely because doing it well means nobody notices anything at all, which is exactly the sign that it was done right.

Hello!