Heartbeat monitors
Most monitors reach out to your service. A heartbeat monitor works the other way: your job calls Asniher. If a ping does not arrive on time, the monitor goes down.
Use heartbeats for cron jobs, scheduled backups, queue workers, and services on private networks that cannot be reached from the internet.
How it works
Each heartbeat monitor has a unique URL:
https://app.asniher.com/api/heartbeat/<token>
Send a GET, POST or HEAD request to it whenever the job succeeds. A successful ping returns 200 with {"ok":true}.
| Setting | Default | Notes |
|---|---|---|
| Interval | Plan minimum | How often the job runs: 30s, 1m, 2m, 5m, 10m, 15m, 30m or 60m, limited by your plan's minimum interval. |
| Grace period | 60 seconds | Extra time allowed before the ping counts as late. 0 seconds to 24 hours. |
The monitor goes down when no ping arrives within interval + grace period of the previous ping. For a new monitor, the clock starts when the monitor is created. The next ping closes the incident and sends a recovery alert.
Heartbeat monitors open an incident as soon as the deadline passes. They do not use the re-check and remote confirmation steps, because a missed ping is already a definitive signal.
Treat the token like a password: anyone with the URL can send pings. If it leaks, delete the monitor and create a new one.
curl
Ping only when the job succeeds by chaining with &&:
./backup.sh && curl -fsS -m 10 --retry 3 https://app.asniher.com/api/heartbeat/<token>
-ffails on HTTP errors,-sSstays quiet but prints errors.-m 10caps the request at 10 seconds so a slow network never blocks your job.--retry 3retries transient network failures.
crontab
A nightly backup at 02:30. The longest interval is 60 minutes, so put the rest of the day into the grace period: interval 60m, grace period 24 hours. The monitor goes down if no ping arrives within 25 hours of the last one.
30 2 * * * /opt/scripts/backup.sh && curl -fsS -m 10 --retry 3 https://app.asniher.com/api/heartbeat/<token> > /dev/null
An every-5-minutes worker with a 5-minute interval and 2-minute grace period:
*/5 * * * * /opt/scripts/sync.sh && curl -fsS -m 10 https://app.asniher.com/api/heartbeat/<token> > /dev/null
GitHub Actions
Ping at the end of a scheduled workflow. For the daily schedule below, use a 60m interval and a 24-hour grace period. Store the URL as a repository secret named ASNIHER_HEARTBEAT_URL.
name: nightly-report
on:
schedule:
- cron: "0 3 * * *"
jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: ./scripts/generate-report.sh
- name: Heartbeat
if: success()
run: curl -fsS -m 10 --retry 3 "$ASNIHER_HEARTBEAT_URL"
env:
ASNIHER_HEARTBEAT_URL: ${{ secrets.ASNIHER_HEARTBEAT_URL }}
GitHub may start scheduled workflows late under load. Leave at least 30 minutes of margin in the grace period for Actions schedules.
Other languages
Node.js
await fetch("https://app.asniher.com/api/heartbeat/<token>", { method: "POST" });
Python
import urllib.request
urllib.request.urlopen("https://app.asniher.com/api/heartbeat/<token>", timeout=10)
Choosing interval and grace
- Set the interval to the job's schedule, not its runtime.
- Set the grace period to the longest normal runtime plus a margin. An hourly job that usually takes 20 minutes and sometimes 40 finishes up to 20 minutes later than usual, so use a 60m interval and a grace period of about 30 minutes.
- For jobs that run less often than hourly (up to once a day), use a 60m interval and add the remaining time as grace. Every 6 hours: grace of 5 hours plus your margin, e.g. 5h 30m. Daily: grace of 24 hours, which gives a 25-hour window.
- Jobs that run less often than once a day cannot be covered precisely, because the maximum window is 25 hours.