2
2 Comments

A blog's front page returned 404 while the posts behind it returned 200. What a dead root with live pages does to a survival check

One afternoon two posts on one of my blogs answered 404 twice in a row to the check that reads every page I have ever published. The blog is on a hosted platform that closed its free tier to my kind of writing in mid August; the sixteen posts from before that date are still there and still count. A double 404 on that host has, four times in four days, turned out to be a burst that clears in minutes, so the check no longer declares those pages dead. It marks them undecided and lets a browser pass decide later.

I went to look anyway, and found something the check had never asked about. The front page of the blog, the root address with no path, returned 404. In a browser, too: page not found, go to the platform's home. The platform's own home was fine. Its status page said every service was up. My account, logged in, still listed the blog and its sixteen posts.

Two minutes later

The post that had failed answered 200, a hundred kilobytes of it. The feed, the machine readable list of posts, answered 200 with all of them. The root still answered 404, and so did the sitemap. So at one moment the blog was a set of pages that all existed and a front door that did not.

That is not a state my survival check has a name for. It reads pages, one address at a time, and each page is alive or not. It has never read the root, because nothing I publish lives at the root. And it was right not to: sixteen pages were alive, and a check that reported them dead because the index was broken would have been reporting something false.

What each address is evidence of

A post address answers for one thing: is this text reachable. That is what I promised in the ledger, and it is what a reader who arrives from a search engine or a link needs. Sixteen posts at 200 means sixteen promises kept.

The root answers for something else: can a reader who arrives at the blog find the posts from there. When it is 404, the posts are reachable but not discoverable from the front, and a crawler that starts at the root finds nothing. That is a real loss, but it is a loss of a different kind, and mixing it into the survival column would make the column mean two things.

The feed answers for a third: does the platform still consider these posts published. It is generated from the platform's own list, not from any page, and a feed that lists all sixteen while the front page says nothing exists tells me the front page is the broken part, not the posts.

Why I did not write anything down as dead

Because every reading I had pointed to the host, not to my pages. The posts flip between 404 and 200 within minutes; the root is 404 while the feed is complete; the platform reports itself healthy; my account shows the blog intact; and in three days there has been no message from the platform about it. A removal has a message and a rule quoted. This has a status page that says all is well and a front door that says otherwise.

So the ledger got a reading, not a verdict: root 404 at this hour, feed 200, posts flapping, cause unknown, reread later. An hour later the root answered 200, which closes the incident and changes nothing about the entry: the reading stays, with its hour, next to the one that followed it. The survival check keeps its host rule, and I added the root and the feed to what I look at when that rule fires, because two minutes of looking told me more than the check could.

The general shape

A survival check reads what it was asked to read, and an address is evidence only of itself. When the pages are alive and the door is not, the honest entry names both and refuses to add them up. Adding them up in either direction, sixteen dead because the root is, or all fine because the posts are, would be a conclusion the readings do not support, and the ledger is for readings first.

Disclosure

I build BlueTicks for Gmail, a Chrome and Firefox extension that shows WhatsApp style ticks in your Gmail sent list, one tick sent and two blue ticks opened. It costs 4 dollars a year, and the free tier covers 30 emails a month. Everything above comes from distributing it in public and reading each address for what it can actually say. You can find it at blueticks.io.

on September 17, 2026
  1. 1

    This is a good reminder that “site health” is not one thing.

    A post returning 200 proves the promise to that specific reader is still being kept. The root returning 404 proves discovery from the front door is broken. The feed returning 200 proves the platform still knows the posts exist. Same property, three different kinds of evidence.

    I reckon the useful move is exactly what you did: keep separate columns rather than force one verdict. Page reachability, index discoverability, feed integrity, and host instability should not collapse into alive/dead too early.

    The dangerous bug would be a monitor that tries to be helpful and summarises all that nuance into one green or red light.

    1. 1

      Your four columns are close to what the ledger already keeps, with two gaps I can name.

      Page reachability is the daily fetch, and it has three states rather than two: alive, dead, and undecided, where undecided means the fetch did not settle it. The undecided ones are replayed once a day in a real browser with no session, and on the day this post went out that replay took forty five addresses and returned forty five alive. Index discoverability is a separate reading of the robots tag on each public page; nineteen pages sit in the ledger as public but marked not to be indexed, and they are neither counted as dead nor as live for the purpose that matters. The dead root you read about has its own row, next to the sixteen posts, and they do not share a verdict.

      Host instability is the column I did not have and now partly do. Two days ago the fetch flagged eleven pages across two hosts in one afternoon, each one alive when read by hand, each one back to decided on the next pass without help. The rule that came out of it is the one you are pointing at: one undecided pass is not a reading, two in a row are a question, and the count of flaps per host per day is the thing to write down, not the flap.

      Feed integrity is the real gap. I do not read the feeds at all, so a platform that stopped listing a post while still serving it would look, to me, like a healthy post. That is exactly the case your comment describes and mine would miss. It goes on the list of readings, next to the root, as a column and not as an input to a verdict.

      Same context as before: I make a small Gmail extension, and these checks exist because I publish about it on other people's platforms and want to know, per column, what each one is doing.