The change is fine. The problem is the layers in between.
When someone visits your site, your shiny new file doesn't get beamed straight onto their screen. It travels through a chain of steps, and your change can get stuck at any one of them:
- Your files. The actual HTML sitting in your repository or on your host.
- The build/deploy step. Most modern hosts publish a fresh copy of your site every time you push. If that didn't run, your live site is still the old version no matter what your files say.
- Routing and redirect rules. Quiet instructions that send one address to another, or serve a different file than the URL implies.
- The CDN edge cache. A network of servers around the world that keep copies of your pages close to visitors so they load fast. Fast is wonderful — until it's handing out a copy you already replaced.
- The browser cache. Your own browser hanging onto an old copy to save itself a download.
The skill in debugging this isn't trying harder. It's working out which of those five links is holding the old version — and there's a quick test for each one.
First, rule out the dumbest cause: your own browser.
Do a hard refresh (Ctrl+Shift+R, or Cmd+Shift+R on a Mac), open the page in a private/incognito window, or just pull it up on your phone or a browser you haven't touched today. If a brand-new browser still shows the old page, your browser is innocent — the stale copy is coming from somewhere further up the chain. That's one minute of work, and it knocks out an entire category of causes.
The one test that splits the problem in half.
This is the trick worth memorizing: add a meaningless query string to the end of the URL — ?x=123, or honestly ?anything. To a CDN, a different query string looks like a different address, so it skips its saved copy and asks your real site directly. Then compare the two:
- If ?x=123 shows the new page but the plain URL still shows the old one → the cache is your culprit. Your real site is already correct; the CDN is just serving a stale copy. Go purge it.
- If both versions are wrong → the cache is innocent. Your change never reached the origin in the first place. Now you're looking at a deploy problem or a routing problem.
When the cache is innocent: did your change actually go live?
Two usual suspects. First, the deploy never ran or quietly failed — open your host's deployment history and confirm the latest build succeeded and matches your latest commit. Second, you're looking at a stale snapshot: if your repository URL has a long random-looking commit ID buried in it, you're staring at a frozen point in time, not the live site. Switch back to your main branch. And keep this distinction close — saving a change on your computer (committing) and sending it to your host (pushing) are two separate actions. A commit you never pushed will never, ever go live.
The sneaky one — redirects, and the page that refuses to 404.
A redirect file (often literally named _redirects) is just a list of rules that reroute traffic. The status code on each rule matters far more than most people realize:
- A 301 is a permanent redirect. The address in the bar changes to the new one. Use this whenever you move a page — it also hands your old page's search ranking to the new URL, so you don't quietly torch your SEO.
- A 200 is a rewrite. The address stays the same, but a different file gets served behind it.
That 200 rewrite is exactly where deletions go to die. A catch-all rule that says "send everything to the homepage" — or a host default that does the same thing when no 404 page exists — means every address that doesn't match a real file quietly serves your homepage with a cheerful "200 OK." So a page you deleted looks alive; it's just showing the wrong content. Worse, search engines see a genuine "success" at a URL that should be gone. That's called a soft 404, and it clutters your site in their index and wastes the crawl budget you'd rather spend on pages that exist.
A file structure that keeps you out of trouble.
A handful of habits prevent most of the haunting before it starts:
- One folder per page, each with its own index.html. That gives you clean addresses like /blog/my-post/ instead of /blog/my-post.html, and it's what most hosts expect.
- Put a real 404.html at the root. On a lot of static hosts, simply not having one makes the host assume your whole site is a single-page app and serve your homepage for every unknown URL — the exact trap above. A 404 page switches that behavior off and lets dead links honestly say "not found."
- Keep your slugs consistent. The link in your blog index, the folder name on disk, and the page's own canonical tag should all spell the same thing. A canonical pointing at a different URL than the page actually lives on tells search engines to rank a version that may not even exist.
- When you move or rename a page, add a 301 from the old URL to the new one. Visitors with the old link still land in the right place, and you keep the ranking you earned.
Purge, then verify — in that order.
Once you've confirmed it really is the cache, clear it. Most CDNs let you purge a single URL or purge everything; a single URL is the gentle, surgical option, while purge-everything is the simplest choice for a small site. Give it up to a minute, then reload the plain URL. For peace of mind, load it with your ?x= cache-buster too: if the plain and busted versions now match, you're done. If only the busted one is right, the purge didn't take — purge again, or go hunting for an aggressive "cache everything" rule that's overriding you.
The five-minute checklist.
- Fresh browser still wrong? → it's not your browser.
- ?x=123 right but the plain URL wrong? → it's the cache. Purge it.
- ?x=123 also wrong? → it's the deploy or routing, not the cache.
- Deploy history shows your latest commit, built successfully? If not, push and redeploy.
- A "deleted" page still resolving to something? → hunt for a catch-all rewrite or a missing 404.html.
- Moved a page? → 301 the old URL and make the canonical match the new one.
Caching, redirects, and 404s aren't the enemy. They're what make your site fast, keep your old links alive, and tell search engines the truth about what exists. They only bite when they're invisible. Once you can see the layers, the "haunted" page that won't change stops being a mystery and turns into a thirty-second fix.