Browse documentation

Pharos / Docs / v1.0.1

How checks work

Updated 2026-10-22 · Pharos 1.0.1

One command does all of it. The scheduler calls the plain form every minute; --force is the diagnostic tool.

php artisan pharos:check          # only checks that are due
php artisan pharos:check --force  # every enabled check, with output

The four probe types

TypeTargetUp when
HTTPA full URLThe response code is 200 to 399 and, when you set one, the expected text is in the response. Redirects are not followed. TLS is verified.
TCPhost:portThe socket connects.
DNSA record nameA record of the chosen type has the value you expect.
HeartbeatA generated tokenSomething called in within two intervals.

Expected text, DNS records and certificate expiry are covered under DNS, keyword and certificate checks. A check can also be run from other networks: see Probe locations. How long each run took is kept for the latency chart.

What turns a component red

A component goes to Major outage once consecutive_failures reaches the check's retry count, two by default. One failure is never enough. The first healthy result flips it straight back to operational.

With the defaults, an HTTP, TCP or DNS target is red about two minutes after it starts failing. A heartbeat takes roughly two intervals plus one more run, because silence has to last before it means anything.

Two situations set Degraded performance instead of red. An HTTPS check that still answers but whose certificate has 3 days or less left, and a check with probe locations that has too few fresh results to decide. Neither opens an incident.

What opens and closes an incident

Crossing the retry threshold opens an incident named {component} unreachable, status Investigating, impact major, with one automatic update naming the probe error. A grouping key stops a second incident being opened while one is already open, and it is what powers the repeat-outage counter on the incidents list.

After three consecutive successful checks the incident closes itself and posts a closing update. Incidents you created by hand are never closed by a check.

Heartbeats

POST https://status.example.com/api/v1/heartbeat/hb_xxxxxxxxxxxxxxxxxxxxxxxx

No authentication header: the unguessable path is the credential, so a backup script needs no token. Call it only when the job actually succeeded:

# the status page hears about it only if restic exits 0
30 3 * * * restic backup /data && curl -fsS -m 10 -X POST \
  https://status.example.com/api/v1/heartbeat/hb_xxxxxxxx >/dev/null

Set the component's interval to the ping frequency. A job pinging every five minutes wants an interval of 300, which gives it a ten-minute grace period.