Uptime monitoring and a status page from one open-source project: checks from several regions, incident updates, and a public page your users can subscribe to.
Build me uptime monitoring and a status page instead of a hosted OpenStatus: checks from several places, and a page that answers "is it down or is it just me". Read this first: OpenStatus is open source and self-hosting it is a real answer — the fee buys hosted regions and a status page you do not operate. Build this when you want the regions to be machines you rent, and note the one rule that outranks everything: the status page must not live on the infrastructure it reports on. STACK - Node 20+ with Fastify for the control plane - SQLite through better-sqlite3, WAL mode - Probes as small agents polling for work, one per region — each is a very cheap VPS somewhere else - Caddy in front - The status page as a separate deployment, elsewhere THE DATA MODEL - monitors: id, name, kind, target, method, headers_json, body, assertions_json, interval_seconds, timeout_ms, regions_json, degraded_ms, confirmations_required, is_active, muted_until - checks: id, monitor_id, region, status, response_ms, dns_ms, connect_ms, tls_ms, ttfb_ms, status_code, error_kind, error_message, tls_expires_at, checked_at — append-only - incidents: id, monitor_id, opened_at, closed_at, cause_check_id, regions_json, confirmed_at, notified_at - status_pages: id, slug, name, custom_domain, is_public, password_hash, theme_json - components: id, status_page_id, name, group_name, position; component_monitors: component_id, monitor_id - announcements: id, status_page_id, kind, title, status, started_at, resolved_at, components_json - announcement_updates: id, announcement_id, body_md, status, at — append-only, so the incident history is a record rather than a current state - subscribers: id, status_page_id, kind, target, token, confirmed_at, unsubscribed_at, components_json CHECKS - HTTP with assertions on status, headers, body content, a JSON path, and response time - TCP, DNS resolution, and TLS expiry as its own check with a warning window measured in weeks - Timing broken into DNS, connect, TLS and time to first byte. 'It is slow' is not actionable; 'TLS negotiation takes two seconds from Singapore' is - A degraded threshold separate from the timeout, so 'up but three times slower' is a state rather than a silence MORE THAN ONE REGION, WHICH IS THE QUESTION BEING ANSWERED - Each probe has a region name and a token, long-polls for work, and posts results back with timings - One region failing is a network event. An incident opens only when the configured number of regions agree, and the threshold is per monitor - On a failure, re-check immediately from a different region before declaring anything. Looking again is the cheapest false-alarm prevention there is - The regional breakdown is shown on the incident and on the status page, because 'down for Europe, fine elsewhere' is a different message to your users than 'down' - Probe health is itself monitored: a region that stops reporting is an alert, not silence THE STATUS PAGE - Its own deployment, on a different machine, at a different provider, on a different network. Say it in the first line of the deployment instructions - It serves from a cache that survives the control plane being unreachable, showing the last known state with its timestamp rather than an error. The page's only job is to work on the worst day - Components grouped, each with its current state and 90 days of history as one bar per day, computed from checks at query time - Uptime percentage with its window and definition written beside it. Everybody computes uptime differently and a number without a definition is decoration - Incidents with a written update history — investigating, identified, monitoring, resolved — and maintenance announced in advance - Subscribers by email, webhook, RSS and Atom, per component, with confirmation and one-click unsubscribe - Static, fast, no framework. Everybody loads it at once, precisely when things are going wrong ALERTING - Escalation after N confirmed failures; channels for email, webhook, chat and a shell command - Recovery always, in the same channel - Muting with an end time, never indefinitely - Maintenance windows suppress alerts and say so on the page - Deduplication so one bad deploy is one alert rather than nine hundred OPERATIONS - .env: DATABASE_PATH, BASE_URL, PROBE_TOKEN_SALT, SMTP_URL, SESSION_SECRET - Migrations on boot, each once - Checks reduced to hourly summaries after a stated window, computed from the rows before they are pruned - Nightly backup off the machine, restore script - Health endpoint reporting every probe's last contact WHAT MATTERS MOST Multi-region confirmation and where the page lives. Build the confirmation rule first — a monitor that pages you for one region's packet loss gets muted, and a muted monitor is worse than none — and deploy the status page somewhere else before you deploy anything else at all. Give me the repository, the probe agent, the separate status page deployment, migrations, .env.example, and a README with deploy steps for the control plane, a second region, and the page on independent infrastructure.
What you lose
- Checks from multiple regions, so "is it down or is it just me" has an answer
- A status page hosted somewhere other than the infrastructure it reports on, which is the whole point of one
- Subscriber notifications by mail and webhook during an incident
If you would rather not build
- Gatus, if you want checks defined in YAML
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $30/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
OpenStatus
$0The product itself: monitoring and status pages, self-hostable.
openstatusHQ/openstatusfree · open source
Uptime Kuma
$0A self-hosted monitor with a status page and many notification channels.
louislam/uptime-kumafree · open source
Why this verdict
our own opinion · changed only by a person
85/100
Verdict yes at 85. Checks and a page are simple; the part people get wrong is hosting the status page on the same infrastructure that goes down.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about OpenStatus
answered from the record above
Is OpenStatus free?
No — the plan we track is $30 a month. Starter at around $30/month billed monthly; the software is open source and free to self-host.
Can you replace OpenStatus by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 85 out of 100, build time one session. Read what you lose before you decide.
How much does OpenStatus cost?
$30 a month on Starter — $360 a year. Recorded 10 Aug 2026.
What do you lose by replacing OpenStatus?
Checks from multiple regions, so "is it down or is it just me" has an answer; A status page hosted somewhere other than the infrastructure it reports on, which is the whole point of one; Subscriber notifications by mail and webhook during an incident. If any of those carry weight for you, keep paying.
Is there an open-source alternative to OpenStatus?
Yes: OpenStatus, Uptime Kuma. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

