Docs menu

Heartbeats

Most monitoring tells you when something happens. A heartbeat tells you when something stops happening: the nightly backup that silently quit, the cron job that never ran, the server that dropped off the network. If you know the pattern as a dead man’s switch, this is it.

A heartbeat isn’t a separate object to manage: it’s a kind of topic. The watched thing checks in on a schedule with a single GET. If check-ins stop for longer than the topic’s interval (plus a grace period), Pinglet publishes an urgent alert to that same topic, so everyone subscribed to it gets a push, and the topic’s feed is the heartbeat’s history.

1. Create a heartbeat topic

In your namespace dashboard at pinglet.dev, open New topic and pick the type:

Type What it is
Push The default. You publish messages to it.
Heartbeat It watches for check-ins and alerts its own subscribers when one is missed.

Choosing Heartbeat adds two more fields:

  • Expect a check-in every: the interval, in seconds, minutes, hours or days,
  • Grace period: slack before it fires. Optional; zero by default.

A topic’s type is fixed at creation, because it decides what the topic is. Heartbeats are created from the dashboard; POST /v1/{ns}/topics and publish-by-name both mint ordinary push topics.

2. Check in on a schedule

The topic’s page shows its check-in URL:

https://pinglet.dev/v1/ping/<token>

The token is the capability: no API key needed to check in. It is deliberately not the topic key: the check-in URL goes to the machine being watched, the subscribe link goes to people. Treat the check-in URL like a key. Editing the schedule doesn’t change it.

Have the watched thing hit the URL each time it does its job. For a cron job, append the ping to the command:

# crontab: nightly backup at 02:00, check in on success
0 2 * * * /usr/local/bin/backup.sh && curl -fsS https://pinglet.dev/v1/ping/<token>

The && matters: the ping only fires when the job succeeds, so a failing backup stops the check-ins and trips the heartbeat.

A healthy check-in returns 200 ok. An unknown token returns 404: a typo’d URL fails loudly instead of the heartbeat silently going dark.

A newly created heartbeat starts with a full interval already on the clock, so it can’t fire before the first check-in is even due.

3. What fires

  • Down: once the interval + grace passes with no check-in, the topic flips to Down and publishes an urgent, error-level alert to its own subscribers; it breaks through Do Not Disturb like any urgent message.
  • Recovery: the next successful check-in publishes a success-level “back to healthy” notice.

Each transition alerts once: a heartbeat that stays down doesn’t re-alert every sweep, and a recovery fires at most once even under concurrent check-ins.

Heartbeat alerts are system messages: they deliver even if your namespace has hit its monthly notification cap; being over quota shouldn’t hide the news that your backups stopped.

4. Watch and adjust it

On the dashboard, a heartbeat topic’s card reports its health in place of the usual last-message badge: OK, Down, or Paused. Its Settings page lets you:

  • change the schedule: saving re-arms the clock from now, so widening an interval never leaves a heartbeat instantly overdue against its old deadline,
  • pause and resume: a paused heartbeat never fires; resuming re-arms it with a fresh full interval.

Everything else works exactly as it does for a push topic: the same share link and QR code, the same public feed, the same subscription flow in the app. Whoever receives the alerts never has to know the topic is a heartbeat.

Ideas

  • Backups: ping after a successful pg_dump/restic run.
  • Cron & scheduled tasks: anything in a crontab or task scheduler.
  • Hosts: a once-a-minute ping from a box that must stay up.
  • People & processes: anything that should happen on a rhythm and quietly might not.