Skip to content

Monitors and check types

The monitor list of a project: seven services with type, check regions, status label and state dot.

Each row is a service: its name, its type, the regions it is checked from, and the last confirmed state as a dot. The label on the right shows whether the monitor is active or paused. A paused monitor stays in the list with its full history and resumes checking when you switch it back on.

Monitors reach beyond network addresses. The certificate monitor in the list checks from one region, and the heartbeat receives pings from its job instead of probing from outside.

http, http_headers, tcp, dns, dns_hygiene, domain, ssl_cert, smtp, imap, ping, traceroute, agent, and heartbeat. The check-type reference explains each one in plain language. The sections below cover the configuration.

  • Assertions: expected status code, a keyword the body must contain, or a regular expression against the body.
  • Inline subchecks: an http monitor carries TLS-certificate (expiry, issuer, self-signed detection), security-header, and DNS-hygiene subchecks, so one monitor covers what used to take four.
  • Redirects: followed up to 5 hops. Perstat validates every hop against SSRF targets (private ranges, link-local, metadata endpoints) before fetching it.

Checks run across all A and AAAA records with per-family and per-IP results. Whether an IPv6-only failure counts as degraded or as failed is your call, per monitor. dns_ms is reported apart from total latency.

A dns monitor compares the answer set against your expectation, and it can cross-reference its answers against another monitor’s answer set. A divergence runs through the normal incident pipeline. dns_hygiene checks SPF, DMARC, and CAA as configuration. domain watches NS, SOA, DNSSEC, and WHOIS expiry.

Asking one specific nameserver. By default, a dns monitor asks Perstat’s own resolver, so it measures the zone as a whole, cache included. Set server (a name like a.example-ns.net or an IP), and the check asks exactly that server directly, with no cache in between. That is how you see a single nameserver of a group fail or answer differently from its siblings, which a check against the whole zone cannot show. Combined with a cross-reference between two such monitors, a divergence between two servers becomes an incident.

With anycast, each check region reaches the node closest to it, so several regions cover several physical nodes of the same address. The address actually reached is recorded with the result. When the server reports NSID or id.server, you also see which node answered.

You set the interval per monitor, down to your plan’s floor: Free 300 s, Pulse 60 s, Sentinel 30 s, Command 15 s, Enterprise 10 s. The web form offers 30 seconds to 1 hour. The REST API and MCP accept any interval from your plan’s floor up to 24 hours, including 15 s on Command and 10 s on Enterprise. Full limit tables are on plans and limits.

The agent type binds a monitor to a host agent: availability with a grace period, CPU, memory, and disk against thresholds, and named services with anti-flapping grace. Missing data counts as pending, never as a false alarm. A silent agent counts as down.

The heartbeat type inverts the direction: instead of Perstat calling your service, your job calls Perstat. It is the right type for a cron run, a batch import, a backup, anything with no address to probe.

Each heartbeat has two endpoints, and your job decides which one to call:

https://api.perstat.io/ping/<token> # finished cleanly
https://api.perstat.io/ping/<token>/fail # ran, but something is wrong

Both accept GET or POST, so curl in a shell script is enough. The exact URL for a monitor is on its detail page in the app and available through the API, and an agent gets it over MCP when it creates the monitor. Wire it into the job right after creating the monitor: coverage starts with the first ping.

Two settings decide when it breaches. period_seconds is how often you expect the job to report, from 30 seconds up to 30 days. grace_seconds is the tolerance on top, so a backup that occasionally runs long pages nobody. Set the grace to a real fraction of the period rather than to a token minute.

  • Silence past the period plus the grace breaches.
  • A call to the failure endpoint breaches at the next evaluation, within about half a minute, instead of waiting the period out.

A heartbeat stays unknown until its first ping arrives, because a schedule starts counting once your job has confirmed it.

Because your side chooses the endpoint, a heartbeat can carry any condition a script can decide, beyond “the job ran”. A timer that checks a queue depth, a record count, or the size of a directory, and then calls the matching endpoint, turns a local measurement into an incident:

Terminal window
if [ "$(records)" -ge 1000 ]; then
curl -fsS -m 10 "https://api.perstat.io/ping/$TOKEN" >/dev/null
else
curl -fsS -m 10 "https://api.perstat.io/ping/$TOKEN/fail" >/dev/null
fi

This expresses conditions that a threshold on a host metric cannot, such as a count that dropped below its target. One heartbeat carries one condition, so give each assertion its own monitor.