Uptime Monitoring

A Status Page Won't Wake You Up — Why We Built a Dead-Man Watchdog Instead

By Josh Comstock · Updated June 2026 · ~6 min read

A digital clock glowing in a dark bedroom late at night

Here's an admission that stings a little coming from a shop that ships server tooling: our own server went down one night, and we didn't know until morning. The monitoring "worked," technically — a message landed in a channel, right on schedule, where it sat in the dark with nobody looking at it. We read it over coffee like archaeologists. The outage was hours old by then, and every minute of it had been announced to a room with the lights off.

That morning is why Foghorn exists. But before we wrote a line of it, we went looking at what was already out there — because surely somebody had built the small thing we wanted.

Every Uptime Tool Wants to Be a Product

Every serverless uptime project we could find is a status page that also monitors. Dashboards. Ninety-day history bars. Multi-region checks, response-time graphs, database migrations, a UI to theme. And to be clear — those are all good things, built by people who care. If you want a public status page for your customers, projects like Uptime Kuma and UptimeFlare do it well, and we'd point you at them without hesitation.

But ask the 2am question. When the box dies at 2am, who's looking at the dashboard? Who's watching the history chart fill in? What good is a beautiful ninety-day uptime bar to a man who's asleep?

When your server dies at 2am, a Discord ping doesn't wake you up.

A text does.

An Alarm, Not an Observatory

Once you frame it that way, the design almost writes itself. At 2am you need exactly one bit of information — it's down — and hours later, one more: it's back. You don't need the response-time percentiles. You don't need the graph. You don't need to know it's still down at minute forty-one, because you've been up since minute two.

And that last point matters more than it looks. A monitor that messages you every failing minute sends 360 messages over a six-hour outage — and somewhere around the third hour, you mute it. We've all done it. A muted monitor is no monitor at all; alert fatigue doesn't announce itself, it just quietly turns your alarm back into a status page. So the rule at the center of Foghorn is the dead-man switch rule: speak only on the transition. One message when the server goes down. One message when it comes back. A six-hour outage costs you two texts, not 360.

What We Built

The whole thing is one cron-triggered Cloudflare Worker — one source file. Every minute, Cloudflare's cron fires it and it fetches each URL you're watching, cache-busted so it always hits the origin and never a cached copy. Any 2xx or 3xx counts as up. A 4xx, a 5xx, a ten-second timeout, or a refused connection all count as down — if your homepage starts throwing 500s, that's an outage, whatever the TCP handshake thinks.

One bad check isn't an outage, though. Each URL keeps its own failure streak, and only after a configurable run of consecutive failures — the default is 2, call it two minutes of confirmed downtime — does the DOWN alert fire. Then it's quiet until the recovery, when a single UP text closes the loop. Two notifiers, use either or both: Twilio SMS, which is the reason the project exists, and a generic webhook that works as-is with a Slack or Discord URL. And if the alert itself fails to send — Twilio rejects, the webhook 500s — the Worker doesn't shrug and move on; it treats the transition as uncommitted and retries the next minute until something actually delivers.

The Monitor Can't Live in the Blast Radius

One more thing we wanted that an on-box cron job can never give you: independence. A watchdog running on the server it watches dies with the server — the outage takes your alarm down with it, which is the one moment the alarm existed for. The classic fix is a second VPS to do the watching, but now you're paying for another box, patching another box, and quietly wondering what's watching that.

Putting the watchdog on Cloudflare's edge ends the regress. It runs outside the blast radius of everything it monitors — different network, different failure domain, no server of ours anywhere near it. There's nothing to keep alive because there's nothing to host.

On Purpose, and Staying That Way

So that's the entire feature list: check every minute, confirm, one text down, one text up. No status page. No uptime history. No UI. We keep the surface area small enough to read over coffee and simple enough to never touch again — and feature requests that would grow it into a status page will be lovingly declined, because the moment it becomes a product to maintain, it stops being the thing we needed at 2am.

It's an alarm. Alarms should be boring.

See how Foghorn works →

Related: The free-tier arithmetic — how it runs on zero KV writes while healthy · Foghorn.

← All articles