Help center / Checks

Heartbeats (cron jobs)

Ping URLs for backups and scheduled jobs, with snippets for cron, shell, Rails, Laravel, Node and Python.

How heartbeats work

A heartbeat watches something that should happen on a schedule. Instead of Pingerer checking your job, your job checks in with Pingerer: when it finishes, it requests the heartbeat's ping URL. If a ping doesn't arrive by the deadline, the heartbeat is down and you're alerted. The next ping resolves it.

  • Period: how often the job runs (every 5 minutes up to weekly).
  • Grace: how late a ping may be before it counts as missed, to allow for jobs that take a while.
  • The deadline is the last ping (or when you created the heartbeat) plus the period plus the grace.

Ping URLs

Each heartbeat has its own URL with a secret token, shown on the Heartbeats page:

https://pingerer.com/hb/YOUR-TOKEN        # success
https://pingerer.com/hb/YOUR-TOKEN/fail   # the job failed: alert now

GET, POST and HEAD all work (send /fail as a GET or POST). Link previews, like Slack's when you paste the URL, aren't counted. Anyone with the URL can ping it, so treat it like a password. Pinging is limited to 30 requests a minute per heartbeat.

cron

# every night at 3am; ping only if the job succeeded
0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 https://pingerer.com/hb/YOUR-TOKEN > /dev/null

Shell script

#!/bin/sh
if /usr/local/bin/backup.sh; then
  curl -fsS -m 10 --retry 3 https://pingerer.com/hb/YOUR-TOKEN
else
  curl -fsS -m 10 --retry 3 https://pingerer.com/hb/YOUR-TOKEN/fail
fi

Ruby on Rails

# app/jobs/nightly_backup_job.rb
require "net/http"

class NightlyBackupJob < ApplicationJob
  PING = "https://pingerer.com/hb/YOUR-TOKEN"

  def perform
    Backup.run!
    Net::HTTP.get(URI(PING))
  rescue => error
    Net::HTTP.get(URI("#{PING}/fail"))
    raise
  end
end

Laravel

// routes/console.php (or app/Console/Kernel.php)
Schedule::command('backup:run')
    ->daily()
    ->pingOnSuccess('https://pingerer.com/hb/YOUR-TOKEN')
    ->pingOnFailure('https://pingerer.com/hb/YOUR-TOKEN/fail');

Node.js

const PING = "https://pingerer.com/hb/YOUR-TOKEN";

async function main() {
  try {
    await runBackup();
    await fetch(PING);
  } catch (error) {
    await fetch(`${PING}/fail`);
    throw error;
  }
}

main();

Python

import urllib.request

PING = "https://pingerer.com/hb/YOUR-TOKEN"

try:
    run_backup()
    urllib.request.urlopen(PING, timeout=10)
except Exception:
    urllib.request.urlopen(PING + "/fail", timeout=10)
    raise

From the CLI

pingerer heartbeats ping "Nightly backup"
pingerer heartbeats ping YOUR-TOKEN --fail   # by token, no login needed

Tips

  • Ping at the end of the job, after it really succeeded, not at the start.
  • Use curl -m 10 --retry 3 so a slow network doesn't hang your job, and a blip doesn't cause a false alarm.
  • Set the grace to a bit more than the job's longest normal run.
  • Heartbeats aren't paused by maintenance windows; pause the heartbeat itself if a job is off on purpose.

Still stuck? Contact us and a person will reply.