Feature

The database is down and the status code says 200

Every uptime checker built on status codes will call this site healthy, because the web server genuinely succeeded. It served a page. The page says the database is gone.

Three readings, because one is not enough

There is no single test that answers this reliably, and a page claiming otherwise would be easy to disprove. Each of the three readings below fails in a different situation, which is precisely why there are three of them.

Reading What it catches Where it fails alone
Failure signatures The message the CMS prints when the connection drops, in several languages. A theme that prints nothing, or an article that merely discusses the error.
Proof string Content that can only come from your database, absent while the page still answers. A page served from cache, where the content is still there.
CMS probe An endpoint that has to reach the database to answer, so a cache cannot cover for it. A site whose API is closed, where the first two readings carry the check.

The signature list is 41 signatures in src/Check/Database.php, counted on 3 August 2026 and held to that number by the engine test suite, which fails if the documentation and the code disagree.

The cache is the part people get wrong

This is the case that defeats a careful setup. A page cache keeps serving the last good version for hours after the database stopped answering, so the page looks right, the proof string is present, and no error text appears anywhere. Everything you would check by hand says the site is fine.

The only way past it is to ask for something a cache cannot have, which is why the third reading exists and why it costs a second request. Nobody discovers this from the outside: they discover it when a client mentions that their new page never appeared.

Down, or merely showing an error

Two things get confused here, and keeping them apart is what makes the availability figure worth sending to a client. A page that cannot be served is an outage. A page that serves its content with a stray warning printed above it is a defect, and putting it in the downtime total would overstate the outage and understate the trust in every other number on the report.

So they are separate causes with separate names, each carrying the excerpt that triggered it and what to do about it. The excerpt is the part that saves time: a signature match is text recognition, and being able to disagree with it in one second is what stops an alert from being ignored.

The three causes, with the remedy shown for each, live in src/Diagnose.php.

Where the others land on this

Every tool in this market can look for a keyword in the response, so every one of them can be made to catch this. The difference is that you have to know it is a problem, decide which words to look for, and set it on each site by hand, in a language that matches the theme you happen to be running.

Here the three readings come with the check that is already watching the page, and the proof string is inferred from the site rather than typed in. If you already maintain a keyword list across your estate, you have solved this: the honest difference is the work, not the capability.

The seven compared in one table, including where they win

Questions about the 200 that lies

Why does a failed database still return 200?

Because the web server did its job. PHP ran, the theme rendered, and a page came back: from the server's point of view nothing failed. WordPress even catches the failure and prints a tidy message inside a perfectly valid response. The status code describes the transaction, not the content, and here the transaction succeeded.

Is matching error text not fragile?

On its own, yes, which is why it is not on its own. Text recognition is fallible in both directions: a blog post about MySQL errors contains the words, and a translated theme may not. So a match is reported with the excerpt that produced it, and it is one of three readings rather than the only one. The excerpt matters more than the verdict, because it lets you disagree in one second.

What does the proof string add to that?

It works the other way round, and it survives a theme you have never seen. Instead of looking for a failure, it looks for something that can only come from your own content, such as a footer line. If the page answers and that text is gone, the page is being served by something that is no longer reading your database, whatever language the error is in.

And the CMS probe?

It is the reading that cannot be faked by a cache. A page can be served from cache long after the database stopped answering, which makes the first two readings look fine. So a second request goes to an endpoint that has to touch the database to reply at all, such as the WordPress REST API. If it answers with real records, the database is alive; if it does not, the cached page was telling you nothing.

Does a visible error on a working page count as an outage?

It is a separate cause, deliberately. A page that serves its content with a stray warning printed at the top is not down, and calling it down would put a cosmetic defect into the availability figure you send your client. It is reported, it is named, and it stays out of the downtime total.

Point it at a site that answers 200

The free check reads the body as well as the code, and tells you when the two disagree. One address, no account.