The claim everyone believes: dead links are the problem. People picture a 404 here and a lapsed domain there, tidy little absences that a broom and a crawler could sweep up once a year.

The row count disagrees. At the start of September we audited a bookmark collection built over roughly eight years, 47,211 rows across two folder trees, and probed 3,907 of the hosts behind them. 880 came back dead. That part matched the folklore. About 23% over eight years works out to roughly 3% of hosts a year, which is as quiet and predictable as rust.

The part nobody warns you about is the 21 domains that did not die.

Findings

Finding zero is mine. Early in the audit I declared that a folder named "Data - Blogs, Feeds, Websites" did not exist. It exists. My search had found it, then truncated the folder path at 150 characters for display, and the name I needed was in the part I cut off. I concluded from my own formatting choice. The fix is now written into the procedure: never truncate the leaf you are searching for. Trust, then check anyway, applies to the auditor first.

Finding one: rot is the quiet failure; hijack is the loud one. Of the 880 dead hosts, most failed honestly. Their DNS no longer resolves, their pages return 404, or a for-sale banner sits where a statistics blog used to be. But 21 domains answered 200 with someone else's business on the line: casino landing pages, sports-betting listicles, one Indonesian slots operation wearing the URL of a former .NET tutorial site. A word-puzzle domain we had bookmarked now redirects to a clone with a different name. A dead link subtracts value. A hijacked link donates your reader to a spam operation, with your credibility as the referral. You only catch these by re-probing old links on a schedule and reading the page titles, because the HTTP status is a cheerful 200 every time.

Finding two: a timeout proves nothing. Two well-known sites timed out for our Python client on every attempt. Both returned 200 instantly to a client with a browser's TLS fingerprint. Some CDNs stall the handshake for tools while waving browsers through, so a timeout cannot be read as death. Our checkers now file timeouts as report-only, and nothing gets deleted on a timeout's testimony alone.

Finding three: the certain-dead set is smaller than the dead set. The audit marked 1,247 bookmark rows dead. The cleanup script we then ran against the live browser profile deleted 556. The gap is deliberate: 480 rows were sites that are alive in languages our probe did not read, 97 were servers having a bad day (a 500 is a mood, not an obituary), and the rest were TLS quirks and tarpits. When the action is deletion, the threshold is not "probably dead." It is "dead twice, two different ways."

What we changed

The site now runs on a tiered schedule instead of good intentions. The curated directories, the dataset guide and the conference registry, get an automated quarterly sweep that opens a pull request with its findings, because those pages promise live links. Upcoming events get their websites probed each quarter; one conference site was serving 500s during the audit, and a human looks before anything is cleared. Feeds and podcasts were already self-auditing through their fetch pipelines. And the quarter-million archived articles get no crawler at all, on purpose: an archive records what was published, and a reader who wants a liveness guarantee should be reading the front page.

One more rule earned its place: a dead link is never silently rewritten to point at an archive.org copy. When a historically important resource dies, its entry may pin a specific Wayback snapshot, and the page says so with a labeled badge. The first entry to use it is a pandemic-era tracker whose domain no longer resolves. The reader clicks knowing exactly what year they are walking into.

This quarter

The audit left three things to re-verify. I re-ran all three on October 7, five weeks after the first probe.

The two timeout sites still stall tool traffic. FRED and the Australian government's energy data portal failed every check our Python client made, four of four, each one running out the clock at about 50 seconds. A client with a browser's TLS fingerprint got a 200 from both in a second or less. Five weeks of the same answer is not a passing mood of their CDN. One of FRED's two failures was a hang-up rather than a stall, and my checker filed that hang-up as broken, the one verdict that can mark an entry dead. Finding two needs a second clause: a timeout proves nothing, and neither does a hang-up.

The conference serving 500s was not down. It was Pragma Tokyo 2026, and its page answered every request we made with a 500 while a browser rendered the full event page anyway: the date, the speakers, a button to apply. A person sees a working page. Every tool that trusts the status line sees a failing server. Its sister page for Pragma Lisbon answers with a 500 too. The October pass over all 467 upcoming events flagged three as broken, and one of the three was DEF CON, whose site answered a browser-like client at once. That is why a human looks before anything is cleared.

Most of the 97 bad-day servers were obituaries. They sat on 33 hosts. Four of those hosts are back with their own content. Two came back as shells, a bare directory listing and a one-line placeholder. One former developer-tool domain now hosts a software-download site, which makes it the 22nd hijack from this collection, and one bookmarked address no longer resolves. The other 25 hosts, holding 89 of the 97 rows, still fail for both of our clients, and 13 of those errors are Cloudflare's, reporting a problem with the server behind it. A 500 is a mood. Five weeks of 500s is an obituary.

Those 25 now clear the bar finding three set for deletion: dead twice, two different ways. Next quarter I will re-check what is left, the two tarpit sites and the four hosts that came back, one of which answered 200 and 500 on consecutive tries.