Uptime checks can’t see a backup that silently stopped running. Heartbeat and cron monitors flip it around: your job calls Pulseback, and silence is the alert.
Your ping URL
Create a monitor of type Heartbeat or Cron and copy its ping URL:
https://app.pulseback.io/hb/<token>
Call it with GET or POST when the job finishes successfully. It answers 200 OK with a plain-text body. The token is the only credential, so treat the URL like a password.
| URL | Meaning |
|---|---|
https://app.pulseback.io/hb/<token> |
The job ran and succeeded. |
https://app.pulseback.io/hb/<token>/start |
The job started. Optional; send it first, then the success ping when it’s done. |
https://app.pulseback.io/hb/<token>/fail |
The job ran and failed. The monitor goes down right away instead of waiting for the deadline. |
Heartbeat or cron?
- Heartbeat — the job runs every period. Set
periodSeconds(30 seconds to 31 days) andgraceSeconds(default 300). The monitor goes down when no ping arrives within period + grace of the last one. Good for workers, queues and anything that runs “about every N minutes”. - Cron — the job runs on a schedule. Set a cron expression in
schedule, itstimeZone(an IANA name likeEurope/Berlin) andgraceSeconds. With the default five-minute grace, a0 2 * * *job inAmerica/Chicagois late at 02:05 Chicago time, daylight saving included.
Either way, a late or failed job opens an incident and pages your escalation policy, like any other monitor.
Examples
curl after a command
Ping only when the command succeeds:
pg_dump "$DATABASE_URL" | gzip > /backups/db.sql.gz && curl -fsS -m 10 --retry 3 https://app.pulseback.io/hb/$HB_TOKEN > /dev/null
-f fails on HTTP errors, -m 10 caps the request at ten seconds and --retry 3 rides out a network blip, so the ping can’t hang your job.
crontab
# m h dom mon dow command
0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 https://app.pulseback.io/hb/3kq9xd7w2m > /dev/null
Use a Cron monitor with the same 0 2 * * * schedule and your server’s time zone.
Start, success and failure
Report the start, then success or failure, so a job that hangs halfway is caught too:
#!/usr/bin/env bash
set -uo pipefail
HB="https://app.pulseback.io/hb/$HB_TOKEN"
curl -fsS -m 10 --retry 3 "$HB/start" > /dev/null
if ./run-nightly-report; then
curl -fsS -m 10 --retry 3 "$HB" > /dev/null
else
curl -fsS -m 10 --retry 3 "$HB/fail" > /dev/null
exit 1
fi
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 2 * * *"
timeZone: "America/Chicago"
jobTemplate:
spec:
template:
spec:
restartPolicy: Never
containers:
- name: report
image: ghcr.io/acme/report:latest
command: ["/bin/sh", "-c"]
args:
- ./run-nightly-report && wget -q -O /dev/null "https://app.pulseback.io/hb/$HB_TOKEN" || wget -q -O /dev/null "https://app.pulseback.io/hb/$HB_TOKEN/fail"
env:
- name: HB_TOKEN
valueFrom:
secretKeyRef: { name: pulseback, key: hb-token }
From code
// After the job's work succeeds.
await fetch(`https://app.pulseback.io/hb/${process.env.HB_TOKEN}`, { method: 'POST', signal: AbortSignal.timeout(10_000) });
Tips
- Give the grace period room for the job’s normal run time, so a slow night isn’t an incident.
- Ping at the end of the job, after the work that matters, not at the start.
- One monitor per job. If ten servers run the same job, give each its own monitor so you know which one stopped.
- Over the API, heartbeat and cron monitors return their
pingUrl. See Monitors & check types.