First heartbeat
Monitor your cron jobs and background workers with a heartbeat check.
What is a heartbeat?
A heartbeat monitor is the inverse of an HTTP monitor. Instead of the platform calling your service, your service calls the platform. At the end of each scheduled job, your script sends an HTTP ping to a unique heartbeat URL. If no ping arrives within the expected window, an incident is triggered.
Use heartbeats for:
- Cron jobs (backups, report generation, data sync)
- Background workers (queue consumers, scheduled tasks)
- Any process that should run on a schedule
Create a heartbeat
- In the sidebar, click Heartbeats.
- Click + New Heartbeat.
- Fill in the fields:
| Field | Example | Notes |
|---|---|---|
| Name | Daily DB backup | Human-readable label |
| Expected interval | 24h | How often the job runs |
| Grace period | 10m | Extra time before alerting |
- Click Save.
- Copy the generated ping URL; you will add it to your script.
Send the ping from your script
At the end of your job (after successful completion), send an HTTP POST to the ping URL:
# Basic curl ping
curl -sS -X POST https://api.howlops.com/api/v1/hb/YOUR_HEARTBEAT_SLUG
Only ping when the job completes successfully. If the job errors, skip the ping: the platform will alert you automatically when the grace period expires.
Integration examples
Crontab
# Add || true so cron itself does not fail if the ping fails
*/60 * * * * /path/to/backup.sh && curl -sS -X POST https://api.howlops.com/api/v1/hb/YOUR_HEARTBEAT_SLUG || true
systemd timer
[Service]
ExecStart=/path/to/worker.sh
ExecStartPost=curl -sS -X POST https://api.howlops.com/api/v1/hb/YOUR_HEARTBEAT_SLUG
Node.js
// At the end of your scheduled job
await fetch('https://api.howlops.com/api/v1/hb/YOUR_HEARTBEAT_SLUG', { method: 'POST' })
.catch(() => console.warn('Heartbeat ping failed'));
Python
import requests
def run_job():
# ... your job logic ...
requests.post('https://api.howlops.com/api/v1/hb/YOUR_HEARTBEAT_SLUG', timeout=5)
if __name__ == '__main__':
run_job()
Cron schedules
Instead of a fixed interval, you can give a heartbeat a native cron expression, ideal when a job runs on an irregular calendar (weekdays at 09:00, the 1st of every month, etc.) rather than "every N seconds".
When creating a heartbeat, switch the schedule toggle from Every N seconds to Cron expression and enter a standard 5-field cron string plus an IANA timezone:
*/5 * * * * every 5 minutes
0 9 * * 1-5 weekdays at 09:00
0 0 1 * * 00:00 on the 1st of each month
30 2 * * 0 Sundays at 02:30
The five fields are minute hour day-of-month month day-of-week. The expression is evaluated in the timezone you pick, so daylight-saving transitions are handled correctly: a 0 9 * * * job fires at 09:00 local time year-round, not at a fixed UTC offset.
A cron heartbeat is considered missed when the most recent scheduled fire time is past the grace period and no ping has arrived since that scheduled time. Existing interval-based heartbeats are unaffected: a heartbeat is either interval-based or cron-based.
Grace period
The grace period is extra time beyond the expected interval (or scheduled cron time) before the platform considers the job late.
Example: interval = 5 minutes, grace period = 2 minutes. The platform triggers an incident at T+7 min if no ping is received. Use a grace period when your job has variable runtime.
Heartbeat statuses
| Status | Meaning |
|---|---|
| Up | Last ping received within interval + grace period |
| Down | Grace period exceeded, incident opened, alert sent |
| New | No pings received yet since creation |
What's next
- First status page: publish uptime data publicly
- Concepts: Heartbeats: full reference for heartbeat configuration
Was this page helpful?