docs

Uptime monitoring

HTTP, TCP, DNS and heartbeat monitors that check your services every minute, including health mode, assertions, thresholds, maintenance, outages, notifications and retention.

A monitor checks one of your public endpoints every minute from outside your infrastructure and tells you when it stops answering. Telemetry describes how your app behaves once a request reaches it. A monitor catches the failures where requests never arrive, such as a DNS mistake, a certificate about to expire, a broken load balancer or a crashed process. A heartbeat monitor works the other way round: your scheduled job calls Unhandled, and the monitor fails when the calls stop.

Open Uptime in the project sidebar. Each monitor belongs to one environment of a project, and the Monitoring tab lists the monitors of the environment you have selected, with their uptime and when each was last checked. The same monitors feed that environment's status page.

Add a monitor

Admins add monitors. Every member with access to the project can see them.

  1. Open the form

    Click Add resource on the Uptime page.

  2. Pick a check type

    Choose HTTP, TCP, DNS or Heartbeat, then enter a name and the target. Turn on health mode if an HTTP URL returns a JSON health report. The check type cannot change after you save.

  3. Run a test check

    Run a test check runs one check with the current settings without saving anything. It shows the result, any warning, the time spent on DNS, connecting, TLS and the first byte, and a command you can copy to reproduce it (curl, nc or dig). Heartbeat monitors have no test check.

  4. Save

    Click Add resource. The first check runs within a minute.

Monitor limits

Each organization can hold a set number of monitors, counted across all its projects and environments: 50 on Starter and 250 on Business. Paused monitors count too. When the organization is full, the form and the MCP create_monitor tool refuse a new monitor with a message naming the limit. Delete a monitor to make room.

Until at least one admin of the organization has verified an email address, the organization can hold 3 monitors and each is checked every 5 minutes instead of every minute. Verifying an email lifts both limits, starting with the next check.

Settings

Namestringrequired

Up to 120 characters.

Descriptionstring

Up to 280 characters. The status page shows it next to the name.

Check typestringdefault HTTP

HTTP, TCP, DNS or Heartbeat. See check types.

Targetstring

For HTTP a URL starting with http:// or https://, for TCP tcp://host:port, for DNS a hostname or dns://hostname. Up to 2048 characters and reachable from the public internet. See private addresses. Heartbeat monitors have no target.

Health modebooleandefault off

HTTP only. Parse the response body as a health report instead of trusting the status code alone.

Expected statusstring

HTTP only. Status codes and ranges that pass, such as 200-299,301. Empty means 200 to 399.

Keywordstring

HTTP and DNS. Text the response body, or one of the DNS answers, must contain. Turn on Fail when the keyword is present to fail on text that must never appear, such as an error banner.

Degraded after (ms)number

HTTP only. A passing check slower than this counts as a warning.

Follow redirectsbooleandefault off

HTTP only. Follow up to 5 redirects and judge the final response.

Record typestringdefault A

DNS only. A, AAAA, CNAME, MX, NS or TXT.

Expected every (s)numberdefault 300

Heartbeat only. How often your job pings, 60 seconds to 7 days.

Grace (s)numberdefault 60

Heartbeat only. Extra time before a late ping counts as missed.

Show on status pagebooleandefault on

Turn it off for internal checks that customers should not see.

Timeout (s)numberdefault 10

1 to 30 seconds per attempt, DNS lookup included.

Custom headerslist

HTTP only. Up to 20 name and value pairs, sent on every check. When a redirect leads to another origin, the headers are not sent there.

Failures to opennumberdefault 3

1 to 10 consecutive failed checks before an outage opens.

Successes to resolvenumberdefault 2

1 to 10 consecutive passing checks before the outage resolves.

Default channelsbooleandefault on

On sends notifications to the organization's uptime default channels. Off sends them only to the channels you pick for this monitor, up to 20.

Pause a monitor to stop its checks and keep its history. Pausing closes an ongoing outage without a recovery notification, and resuming starts the monitor over from Pending. Changing the target or any check setting does the same, so a new URL never inherits the failures of the old one. Deleting a monitor stops its checks right away and removes it from the status page.

Check types

  • HTTP sends a GET request with your custom headers and the user-agent header Unhandled-Uptime/1.0. A status in Expected status passes, 200 to 399 by default; any other status fails with http. Without Follow redirects, a 301 or 302 passes without loading the target. With it, Unhandled follows up to 5 redirects, checks every hop against private addresses, and judges the final response. Unhandled reads up to 1 MiB of the body.
  • TCP opens a connection to the host and port. It passes when the connection is accepted.
  • DNS looks up the record type for the hostname. It fails when the name does not exist or has no records of that type.
  • Heartbeat has no target. Saving it creates a ping URL; call it with GET, HEAD or POST each time your job finishes, for example curl -fsS <ping URL>. The check fails with heartbeat when no ping arrived within Expected every plus Grace, counted from the last ping or, before the first one, from when you created the monitor.

How a check works

  • Network errors that can clear up in seconds (a reset or refused connection, a temporary DNS failure) and HTTP 502, 503 and 504 are retried, up to 3 attempts in total, 2 to 5 seconds apart. A timeout is retried once, since each attempt already waited the full timeout. Other failures, such as a TLS error, a missing DNS name, a 4xx or a keyword mismatch, are not retried. Every check ends within 40 seconds, retries included.
  • A keyword mismatch fails with keyword. A passing check slower than Degraded after counts as a warning.
  • On https:// monitors Unhandled reads the certificate's expiry date. A passing check whose certificate expires within 14 days counts as a warning, and the monitor page shows the expiry date.
  • Unhandled resolves hostnames itself, caching answers for their time to live, so a slow resolver shows up as DNS time instead of a timeout.

Failed checks record one of these error types:

TypeShown as
timeoutRequest timed out
dnsDNS resolution failed
connectionConnection failed
tlsTLS handshake failed
httpUnexpected HTTP response
ssrfTarget resolves to a private or reserved address
keywordKeyword check failed
heartbeatNo heartbeat received in time

For a failed check Unhandled keeps the status code, the response headers and the first 16,384 characters of the body, so you can read the error page your users saw.

Regions

Checks run from Unhandled's own servers. Every configured region checks every monitor, and an outage opens only when a strict majority of the regions that reported in the last 3 minutes agree that the monitor is down: 1 of 1, 2 of 2, 2 of 3, 3 of 4. A failure seen from one place, such as one provider's network, does not page you. The monitor page lists each check with the region it ran from. You cannot pick regions.

Each checker also watches its own network. Before a round of checks it connects to a few public anchors. When none answer, the checker records the round as unknown instead of failing your monitors, and no outage opens. When at least 10 checks in one round, and at least half of all its checks, would open outages at once, the checker holds them for one more minute and opens them only if the failures persist.

Checks share the checker fairly between organizations. Each round takes every organization's most overdue monitor before anyone's second, and one organization runs at most 20 checks at the same time, so monitors that hang until their timeout slow down only their own organization. Each region sends a single host at most 60 checks a minute from one organization, and at most 600 across every organization that monitors it. A check past that budget is not sent and nothing is recorded for it; it moves to the next minute and goes first there, so monitors at a busy host take turns. When you save a monitor that would push its host past your organization's 60, Unhandled warns you and says how often each monitor at that host is then checked.

Private addresses

Monitors only check the public internet. Saving fails when the target's host is localhost, ends in .local, .localhost or .internal, or is a private or reserved IP address. Unhandled also checks the address a hostname resolves to at check time, and again for every redirect it follows. If DNS returns a private or reserved address, the check fails with ssrf and never connects.

Health mode

With health mode on, a passing status code is not enough. Unhandled parses the body as JSON and expects this shape:

json
{
  "isHealthy": true,
  "checks": [
    { "name": "database", "status": "ok", "message": "Connected" },
    { "name": "payments-api", "status": "warning", "message": "Slow responses" }
  ]
}
BodyResult
Invalid JSON, no boolean isHealthy, or no checks arrayFails
"isHealthy": falseFails
"isHealthy": true and some check has status warning or errorPasses as a warning
"isHealthy": true and every check is okPasses

An entry may also carry a meta value. The monitor page shows every entry of the latest report for each period, and the availability timeline highlights warnings.

Outages

One failed check does not open an outage. An outage opens after Failures to open consecutive failures and resolves after Successes to resolve consecutive passing checks. Warnings count as passing. The outage starts at the first failed check, not when it opened, and it keeps that start if you change the thresholds later.

With the defaults, a monitor needs 3 failed checks in a row, about 3 minutes, before anyone hears about it, and 2 passing checks to recover, so a flapping endpoint does not alternate between down and recovered. Raise the failure threshold for a flaky endpoint. Raise the success threshold when you want a longer run of good checks before the all-clear.

Maintenance

During a scheduled maintenance that lists a monitor, the monitor is still checked, but its checks are recorded as maintenance. They do not open or resolve outages, send notifications, or count toward uptime. Failures outside the window count as usual, even on the same day.

Notifications

When an outage opens or resolves, Unhandled sends one round of notifications:

  • An inbox entry for every project member.
  • An email to project members whose Uptime alerts preference is on, with the subject [Down] <name> or [Recovered] <name>.
  • A channel message. With Default channels on, it goes to each channel marked as an Uptime monitors default, and channels marked Only for production environments only hear about production monitors. With Default channels off, it goes only to the channels picked on the monitor, in any environment, and to none if you picked none.

The outage and its notifications are recorded together: if recording them fails, the monitor keeps its previous state and the next check tries again. Channel messages and emails are retried for about 50 minutes, and Slack and Discord get one message when several monitors change within 20 seconds. Webhook channels receive uptime.down and uptime.recovered events, with the payload documented in Notifications.

When an https:// certificate is 14, 7 and 1 days from expiry, project members get one inbox entry and one email each time, with the subject [Certificate] <name> expires in <days>. Certificate warnings do not go to channels.

If the checkers stop running, the Uptime pages say that monitoring is delayed, so stale states are not mistaken for healthy ones.

The monitor page

The monitor page shows the current status, response time, uptime percentage and check count for the last 24 hours, 7 days or 30 days.

  • Availability Timeline splits the range into periods of 1 hour for 24 hours, 6 hours for 7 days, and 1 day for 30 days. Each period is up, warning, down or no data. Click a period to see its average and P95 response time, success rate and health check results.
  • Response Time charts average and P95 response time per period.
  • Incidents comes first and lists the 10 most recent outages with their start and end, who acknowledged them, and whether an outage closed because the monitor was paused or its target changed.
  • Under the incidents, anyone who can see the project can acknowledge, assign and comment on the latest outage. Acknowledging shows the team who is on it. It does not hold notifications.
  • Latest checks opens on Failures and changes: up to 50 failed checks and state changes in the range, newest first. Each entry shows the time spent on DNS, connecting, TLS and the first byte, the response headers, and the first 2 KB of the body. All checks lists the 20 most recent checks with their outcome, status code, response time, attempts and error.
  • Heartbeat monitors show their ping URL and the time of the last ping.

Unhandled keeps check results for your organization's uptime retention: at least 90 days on every plan, unless an admin shortens it. See Data retention.

FAQ