Public beta Monitoring, status pages, on-call and incident evidence

Uptime monitoring with on-call built in.

Quietbeat checks your sites, APIs and scheduled jobs, pages whoever is on call, and moves your status page to the right state. Monitors, status pages, and real paging — one flat price, unlimited teammates.

Start monitoring

10 monitors free · $9 solo · $19 team — flat, no card required

api.example.com Up

HTTP every 30 s example data

167 ms median

Median response time Fastest to slowest recent check Failed checks Example data, replayed faster than real time

Seven examples

Seven kinds of trouble, and what Quietbeat does about each.

Pick one. The checks, the flight log, who gets woken, the status page and every message that goes out, replayed from example data.

quietbeat · console example data, replayed

Seven scenarios, each shown in full below — read top to bottom.

api.example.com starts answering 500

A deploy goes wrong and the health endpoint answers 500. The failed availability check is held and re-probed before anyone is paged, then the rota rings, the page is acknowledged, and the recovery is captured.

api.example.com · HTTP · every 30 s

Checks

20 passing checks, then 12 failing, then 4 passing again

  1. 14:31:30 fra · HTTP 500 in 212 ms — failure 1 of 2
  2. 14:32:00 fra · HTTP 500 — held, re-probing before anyone is paged
  3. 14:32:09 fresh re-probe · HTTP 500 — the incident opens
  4. 14:37:46 fra · 200 in 191 ms — recovered

Flight log QB-4127 · times in UTC

The outage of September 14

14:32:10 incident opened — failure detected, seen from fra
14:32:11 slack notified escalation rung
14:32:12 email notified
14:32:40 evidence preserved
14:33:01 ana@example.com took it — the ladder stopped
14:37:46 recovery evidence captured
14:37:46 recovery confirmed

Assessment · HTTP 500 from the origin

One vantage observed this window — breadth beyond it is unknown.

DNS: ok TCP: ok TLS: ok HTTP: failed

confidence: MEDIUM — The failure signal is specific, but only one vantage observed it — breadth is unverified.

On call

ana@example.com is on-call · until Tue 09:00 CEST

  1. +0 min Slack · #ops
  2. +0 min rota “primary” — the current holder, by email (Ana)
  3. +15 min rota “secondary” — never fired — the ack stopped the ladder

Repeats every 5 min, up to 20 rounds, until someone acknowledges.

Status page status.example.com

All systems up before

4 services monitored, all responding.

Incident in progress 14:32

1 of 4 services affected — details below, updates as they happen.

All systems up 14:37

api.example.com is back — 4 services monitored, all responding.

Subscribers are emailed when it opens and when it resolves.

What goes out the notifier's own text, run over this example

email · the rota holder

DOWN 14:31 UTC — api.example.com

api.example.com stopped answering at 14:31 UTC. The probe saw: HTTP 500.
Checked: https://api.example.com
Slack

DOWN 14:31 UTC — api.example.com

api.example.com stopped answering at 14:31 UTC. The probe saw: HTTP 500.
Checked: https://api.example.com

Quietbeat — availability check re-probed before paging

status subscribers · email

[api.example.com] We're looking into an issue

api.example.com started having trouble at 14:31 UTC. We're on it — updates will follow here and on the status page.
evidence.json · diff
{
  "label": "HTTP",
  "after": "200",
  "recovered": true,
  "before": "200",
  "changed": true,
  "layer": "http",
  "during": "500"
}

the HTTP row, before · during · after

1 Oct · the month in review
api.example.com                99.985%   1 incident

app.example.com stops answering in the night

The rota decides who hears it, at the moment the rung fires — not whoever was on call when you wrote the ladder. The page repeats every five minutes, up to 20 rounds, until someone says they have it.

app.example.com · HTTP · every 30 s · repeat every 5 min Rota paging from Solo

Checks

24 passing checks, then 10 timeouts, then 2 passing

  1. 03:11:34 fra · no response within 10 s — failure 1 of 2
  2. 03:12:04 fra · timeout — held, re-probing before anyone is paged
  3. 03:12:04 fresh re-probe · timeout — the incident opens
  4. 03:41:10 fra · 200 in 150 ms — recovered

Flight log QB-4131 · times in UTC

The outage of September 14

03:12:04 incident opened — failure detected, seen from fra
03:12:05 email notified
03:12:40 evidence preserved
03:17:05 email notified round 1
03:18:40 ana@example.com took it — the ladder stopped
03:41:10 recovery evidence captured
03:41:10 recovery confirmed

Assessment · No response within the timeout

One vantage observed this window — breadth beyond it is unknown.

DNS: ok TCP: unknown TLS: unknown HTTP: unknown

confidence: MEDIUM — The failure signal is specific, but only one vantage observed it — breadth is unverified.

On call

ana@example.com is on-call · until Tue 09:00 CEST

  1. +0 min rota “primary” — the current holder, by email (Ana)
  2. every 5 min the same rung again, up to 20 rounds, until acknowledged
  3. +15 min rota “secondary” — never fired — the ack stopped the ladder

Nobody on the rota? The workspace owner is paged — never a void.

Status page status.example.com

All systems up before

4 services monitored, all responding.

Incident in progress 03:12

1 of 4 services affected — details below, updates as they happen.

All systems up 03:41

app.example.com is back — 4 services monitored, all responding.

Subscribers are emailed when it opens and when it resolves.

What goes out the notifier's own text, run over this example

email · the rota holder

DOWN 03:11 UTC — app.example.com

app.example.com stopped answering at 03:11 UTC. The probe saw: timeout.
Checked: https://app.example.com
status subscribers · email

[app.example.com] We're looking into an issue

app.example.com started having trouble at 03:11 UTC. We're on it — updates will follow here and on the status page.
status subscribers · email

[app.example.com] Resolved

app.example.com is back to normal as of 03:41 UTC. Total impact: 29 min.
evidence.json · diff
{
  "label": "HTTP",
  "after": "200",
  "recovered": true,
  "before": "200",
  "changed": true,
  "layer": "http",
  "during": "timeout"
}

the HTTP row, before · during · after

1 Oct · the month in review
app.example.com                99.931%   1 incident

nightly-backup says nothing at 04:00

The job pings after every successful run. Silence is not a network fact — no vantage observed a failure — so nothing is re-probed: the incident opens when the window and its grace pass, carrying the last run that did happen.

nightly-backup · heartbeat · cron "0 4 * * *" · 1 h grace

Checks

six nightly runs arrived, the seventh did not

  1. Sun 04:00:11 beat · ran 5.0 s · “backup ok, 1.9 GB in 5 s”
  2. Mon 04:00 expected a run — nothing arrived
  3. Mon 05:00:02 window + 1 h grace passed in silence — missed
  4. Mon 08:52:40 beat · the re-run finished — recovered

Flight log QB-4119 · times in UTC

The silence of September 14

05:00:02 incident opened — the heartbeat went silent
05:00:03 email notified escalation rung
05:00:03 slack notified escalation rung
05:00:30 evidence preserved
07:41:15 ana@example.com took it — the ladder stopped
08:52:40 recovery confirmed

Assessment · Heartbeat went silent

No probe observations in the incident window.

confidence: LOW — The evidence identifies a layer but not how far the failure extends.

On call

ana@example.com is on-call · until Tue 09:00 CEST

  1. +0 min email + Slack · #ops
  2. — no rota on this ladder — a backup waits for the morning; nobody is woken

Every monitor has its own ladder. This one never pages the rota.

Status page status.example.com

All systems up throughout

4 services monitored, all responding.

nightly-backup is internal — it is not on the public page.

What goes out the notifier's own text, run over this example

Slack

MISSED 05:00 UTC — nightly-backup

Nothing heard from nightly-backup since 04:00 UTC. Expected a run at 04:00 UTC (cron "0 4 * * *", +1 h grace).

Last run took 5.0s (recent average 4.7s).

Last output received:
backup ok, 1.9 GB in 5 s

Quietbeat — heartbeat silence; nothing to probe

evidence.json · during
{
  "avg_duration_ms": 4700,
  "captured_at": "2026-09-14T05:00:30Z",
  "kind": "heartbeat",
  "last_beat_at": "2026-09-13T04:00:11Z",
  "last_duration_ms": 5000,
  "last_payload": "backup ok, 1.9 GB in 5 s"
}

the capture, as the export carries it

1 Oct · the month in review
nightly-backup                 99.461%   1 incident

pay.example.net's certificate runs out at 09:14

Four warnings went out — 30, 14, 7 and 1 day before — and nobody renewed. At 09:14 the handshake starts failing, the incident opens, and the assessment names the layer that broke.

pay.example.net · HTTPS · every 60 s · expiry watch

Checks

  1. 30 d 15 Aug
  2. 14 d 31 Aug
  3. 7 d 7 Sep
  4. 1 d 13 Sep

the four expiry warnings were sent; 18 passing checks, then 8 failed handshakes

  1. 09:14:00 notAfter — the certificate expires
  2. 09:14:31 fra · TLS handshake refused — certificate expired
  3. 09:31:02 fra · new chain served · 200 in 208 ms — recovered

Flight log QB-4122 · times in UTC

The outage of September 14

09:15:02 incident opened — failure detected, seen from fra
09:15:03 email notified escalation rung
09:15:04 email notified
09:15:30 evidence preserved
09:16:20 ana@example.com took it — the ladder stopped
09:31:02 recovery evidence captured
09:31:02 recovery confirmed

Assessment · TLS handshake failure

One vantage observed this window — breadth beyond it is unknown.

DNS: ok TCP: ok TLS: failed HTTP: not reached

confidence: MEDIUM — The failure signal is specific, but only one vantage observed it — breadth is unverified.

On call

ana@example.com is on-call · until Tue 09:00 CEST

  1. +0 min email
  2. +0 min rota “primary” — the current holder, by email (Ana)

The warnings are notices to your configured alert channels. Only the failed handshake opens an incident and climbs the ladder.

Status page status.example.com

All systems up before

4 services monitored, all responding.

Incident in progress 09:15

1 of 4 services affected — details below, updates as they happen.

All systems up 09:31

pay.example.net is back — 4 services monitored, all responding.

Subscribers are emailed when it opens and when it resolves.

What goes out the notifier's own text, run over this example

email · 7 days before

CERT 7d — pay.example.net

The TLS certificate for https://pay.example.net expires in 7 days, on 2026-09-14. Renew it before it expires.
page subject · 09:15

DOWN 09:14 UTC — pay.example.net

status subscribers · email

[pay.example.net] Resolved

pay.example.net is back to normal as of 09:31 UTC. Total impact: 16 min.
1 Oct · the month in review
pay.example.net                99.962%   1 incident

example.com's MX record points somewhere new

Every six hours the zone is read back record by record. A change is a finding, not an outage: no incident opens and uptime is untouched, but whoever can edit your zone can take your mail — so you hear about it the same day.

example.com · zone watch · every 6 h DNS depth from Solo

Checks

nine record sets read; MX changed, the rest unchanged

Record sets read from the zone
A 203.0.113.10 same
AAAA 2001:db8::10 same
MX 10 mx1.example.com removed
MX 10 mx.mail-relay.example.net added
TXT v=spf1 include:_spf.example.com -all same
NS ns1.example-dns.net, ns2.example-dns.net same
CAA 0 issue "letsencrypt.org" same
  1. 06:37 zone read — nothing changed
  2. 12:37 zone read — MX record changed

Flight log

No incident — a finding

A record changing is not downtime and never touches uptime.

  1. 12:37 email + every channel except the pagers · “DNS record changed — example.com”

On call

ana@example.com is on-call · until Tue 09:00 CEST

No incident and no on-call ladder: the finding goes to email and to every channel except the pagers.

Status page status.example.com

All systems up throughout

4 services monitored, all responding.

A record change is not an outage — the page stays as it is.

What goes out the notifier's own text, run over this example

email

DNS record changed — example.com

The MX record for example.com changed.
Added: mx.mail-relay.example.net
Removed: mx1.example.com

It now reads:
10 mx.mail-relay.example.net

It read before:
10 mx1.example.com

If this was you, nothing to do. If it was not, treat it as urgent: whoever can edit this zone can receive your mail and get certificates in your name.

search.example.com is up, but not fine

Every check still answers 200. After a deploy the rolling p95 climbs past the line you drew, and that is worth a notification — never an incident, so your uptime stays honest.

search.example.com · HTTP · every 60 s · p95 line at 400 ms

Checks

16 checks around 140 ms, then 10 checks between 520 and 900 ms

  1. 16:02 deploy a3f19c2 · search — recorded by CI
  2. 16:03 fra · 200 in 520 ms — still up
  3. 16:12 10-minute p95 878 ms across 10 checks — over the line

Flight log

No incident — up, but not fine

Slow is a notification. Uptime only counts what failed.

  1. 16:12 email + your configured alert channels · DEGRADED

Had it gone down, the incident page would name the deploy: “a3f19c2 · search shipped 10 min before this began”.

On call

ana@example.com is on-call · until Tue 09:00 CEST

No incident and no on-call ladder: the notice goes to your configured alert channels. One notice per hour, at most.

Status page status.example.com

All systems up throughout

4 services monitored, all responding.

Slow is not down — the page stays as it is.

What goes out the notifier's own text, run over this example

email · alert channels

DEGRADED 16:12 UTC — search.example.com

search.example.com is up, but not fine: the 10-minute p95 is 878ms across 10 checks — the line is drawn at 400ms.
Overview · recent deploys
a3f19c2 · search · 14 Sep 16:02

marked by one POST from CI — the GitHub Actions tab below

checkout.example.com fails while Stripe is having a bad hour

checkout declares Stripe as a dependency, so when the incident opens the latest reading of Stripe's status — under 20 minutes old — is named in the alert: as a lead, never as a reason to hold the page back.

checkout.example.com · HTTP · every 30 s · depends on Stripe

Checks

20 passing checks, then 14 failing, then 2 passing

  1. 11:01 Stripe status · major · Partial System Outage
  2. 11:02:14 fra · HTTP 502 in 1.2 s — failure 1 of 2
  3. 11:02:44 fra · HTTP 502 — held, re-probing before anyone is paged
  4. 11:02:52 fresh re-probe · HTTP 502 — the incident opens
  5. 11:48:30 fra · 200 in 241 ms — recovered

Flight log QB-4125 · times in UTC

The outage of September 14

11:02:53 incident opened — failure detected, seen from fra
11:02:54 slack notified escalation rung
11:02:55 email notified
11:03:20 evidence preserved
11:04:02 ana@example.com took it — the ladder stopped
11:48:30 recovery evidence captured
11:48:30 recovery confirmed

Assessment · HTTP 502 from the origin

One vantage observed this window — breadth beyond it is unknown.

DNS: ok TCP: ok TLS: ok HTTP: failed

confidence: MEDIUM — The failure signal is specific, but only one vantage observed it — breadth is unverified.

Declared dependencies, the latest fresh reading when this opened

major Stripe — Partial System Outage

selected because this monitor declares them as dependencies — a lead, not a cause, and never a reason the alert was held back

On call

ana@example.com is on-call · until Tue 09:00 CEST

  1. +0 min Slack · #payments
  2. +0 min rota “primary” — the current holder, by email (Ana)

A vendor outage still pages: your checkout is still down.

Status page status.example.com

All systems up before

4 services monitored, all responding.

Incident in progress 11:02

1 of 4 services affected — details below, updates as they happen.

Incident in progress 11:10 · update posted

Card payments are failing at our payment provider. Checkout is affected; we are following their status page.

All systems up 11:48

4 services monitored, all responding.

Subscribers hear the update you post, word for word.

What goes out the notifier's own text, run over this example

email · the rota holder

DOWN 11:02 UTC — checkout.example.com

checkout.example.com stopped answering at 11:02 UTC. Likely vendor involvement: Stripe — partial system outage. The probe saw: HTTP 502.
Checked: https://checkout.example.com
status subscribers · email

[checkout.example.com] Update

Card payments are failing at our payment provider. Checkout is affected; we are following their status page.
evidence.json · diff
{
  "label": "HTTP",
  "after": "200",
  "recovered": true,
  "before": "200",
  "changed": true,
  "layer": "http",
  "during": "502"
}

the HTTP row, before · during · after

1 Oct · the month in review
checkout.example.com           99.893%   1 incident

How it works

From the first failed check to your status page.

A failed check becomes an incident, a page and a status update without anyone opening a laptop first. You answer the page and choose the words.

  1. Check

    HTTP, TCP, DNS and certificate checks, plus heartbeats from your scheduled jobs: every 60 seconds on Hobby, as often as every 30 from Team up.

  2. Confirm

    A failed availability check is re-probed before anyone is paged: from an independent vantage when one is online, otherwise a fresh probe moments later. If the target keeps failing while confirmation stays out of reach, the incident opens on the accumulated evidence.

  3. Page

    Whoever is on call is paged on the channels they chose, by schedule and rotation. It re-pages up to 20 rounds until someone acknowledges.

  4. Publish

    Your status page moves to the right state on its own. You write the words when you are ready.

Every incident keeps what was seen: the response, the DNS answers, the TLS state, the timing and which vantages actually observed the failure, exportable as JSON for the postmortem or the vendor ticket. Evidence capture runs on every plan, Hobby included, and the AI summary labels each conclusion a hypothesis and says what it could not see.

Your first signal in 60 seconds

Paste one line. Watch the first beat land.

Make a monitor, copy its ping URL, and send it from wherever your work already runs. Every snippet here works against the API today — swap the placeholder for your own token.

Ping a heartbeat · curl

curl -fsS https://quietbeat.dev/b/YOUR_PING_TOKEN

Create a heartbeat monitor, copy its ping URL, and send the first beat. Anything that can make a request can keep a monitor alive.

Watch a cron job · crontab

# a cron job that reports in — GET or POST, body optional
0 4 * * *  backup.sh && curl -fsS https://quietbeat.dev/b/YOUR_PING_TOKEN

The beat only goes out when the job succeeds — a night without one opens the incident.

Mark every deploy · GitHub Actions

- name: Mark the deploy in Quietbeat
  run: |
    curl -fsS -X POST https://quietbeat.dev/api/v1/deploys \
      -H "Authorization: Bearer ${{ secrets.QUIETBEAT_TOKEN }}" \
      -H "Content-Type: application/json" \
      -d '{"ref": "${{ github.sha }}", "component": "api"}'

The last step of a deploy job. An outage that follows it names the commit that shipped.

Beat while the container is healthy · Docker

HEALTHCHECK --interval=60s --timeout=10s \
  CMD curl -fsS http://localhost:8080/health \
   && curl -fsS https://quietbeat.dev/b/YOUR_PING_TOKEN || exit 1

The container pings only while its own health endpoint answers. When it stops, so do the beats.

Create a monitor from a terminal · qb CLI

brew install mightyworks-sk/tap/qb
export QB_API_KEY=qb_YOUR_TOKEN
qb monitors create --name "prod site" --kind http \
  --url https://example.com/health --interval 60

One static binary. --json prints the API response verbatim, for jq and for agents.

Monitors as code · Terraform

terraform {
  required_providers {
    quietbeat = { source = "mightyworks-sk/quietbeat" }
  }
}

provider "quietbeat" {
  host = "https://quietbeat.dev"
}

resource "quietbeat_monitor" "nightly_backup" {
  name              = "nightly backup"
  kind              = "heartbeat"
  interval_seconds  = 86400
  grace_seconds     = 3600
  cron_schedule     = "0 4 * * *"
  schedule_timezone = "Europe/Bratislava"
}

output "backup_ping_url" {
  value = quietbeat_monitor.nightly_backup.ping_url
}

A heartbeat on a cron schedule, its ping URL an output for the job to use. The token comes from QB_API_KEY.

Create a monitor over HTTP · REST

curl -X POST https://quietbeat.dev/api/v1/monitors \
  -H "Authorization: Bearer qb_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "nightly backup", "kind": "heartbeat",
       "interval_seconds": 86400, "grace_seconds": 3600,
       "runbook": "check restic logs first"}'

The same call the CLI and the Terraform provider make. The answer carries the ping URL.

Let your agent set it up · MCP

claude mcp add --transport http quietbeat https://quietbeat.dev/mcp --header "Authorization: Bearer qb_YOUR_TOKEN"

# then, in the session:
# > watch my nightly backup — it runs at 04:00 and takes a few seconds

Add the server once. The agent calls create_monitor and hands back the crontab line.

Pricing

Flat prices. Teammates are free from Team up.

Paid plans differ by scale — monitors, people you can page, history — never by which features you get. Every paid plan starts with a 10-day trial, and annual billing is two months free.

Hobby

$0 forever

free, no card, no clock

Serious monitoring for one person's projects.

  • 10 monitors, every 60s
  • Email alerts; a failed availability check is re-probed before paging
  • Chat channels, webhooks and PagerDuty hand-off
  • 90 days of history
  • Status page, badges, cert-expiry + takeover watch

Solo

$9 /mo

$90/yr — two months free

Every deep check, and a page that repeats.

  • 50 monitors, every 60s
  • Every alert channel, nothing billed per message
  • On-call rotations email the holder; ladders repeat up to 20 rounds until acked
  • 1 year of history
  • Deep checks: DNS depth, CT logs, crawler, private relay

Team

recommended
$19 /mo

$190/yr — two months free

On-call for a team that ships to production.

  • 200 monitors, every 30s
  • 5 pageable people, nothing billed per message
  • Unlimited teammates, rotas and schedules
  • 1 year of history
  • Client reports, branding, status-page locks

Business

$49 /mo

$490/yr — two months free

The whole engineering org on one rota.

  • 500 monitors, every 30s
  • 15 pageable people, nothing billed per message
  • Unlimited teammates, rotas and schedules
  • 2 years of history
  • Everything in Team, at organization scale

Scale

$99 /mo

$990/yr — two months free

Fleet-sized monitoring, same flat bill.

  • 1,000 monitors, every 30s
  • 40 pageable people, nothing billed per message
  • Unlimited teammates, rotas and schedules
  • 2 years of history
  • Everything in Team, at fleet scale

Commercial use welcome on every plan · No price change without 30 days' notice · cancel anytime · annual billing = 2 months free · no metered check-volume charges · Compare every limit

Add your first monitor now. Hear about the next outage before your customers do.

10 monitors free, no card required · runs in the EU (Germany)

Leave anything. One-paste importers bring your monitors across from UptimeRobot, Better Stack, Pingdom, StatusCake, Healthchecks.io, Oh Dear, Opsgenie and Larm with names, intervals and heartbeats intact, in about two minutes.