DOCS

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.

DAILY BACKUP JOB
UP
Next check in 4h 51m

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

  1. In the sidebar, click Heartbeats.
  2. Click + New Heartbeat.
  3. Fill in the fields:
FieldExampleNotes
NameDaily DB backupHuman-readable label
Expected interval24hHow often the job runs
Grace period10mExtra time before alerting
  1. Click Save.
  2. 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:

bash
# 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

bash
# 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

ini
[Service]
ExecStart=/path/to/worker.sh
ExecStartPost=curl -sS -X POST https://api.howlops.com/api/v1/hb/YOUR_HEARTBEAT_SLUG

Node.js

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

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

StatusMeaning
UpLast ping received within interval + grace period
DownGrace period exceeded, incident opened, alert sent
NewNo pings received yet since creation

What's next

Was this page helpful?