← Blog  ·  October 2026

Heroku Scheduler Monitoring: Get Alerted When Jobs Fail Silently

Heroku Scheduler has no built-in failure alerts. Here's how to know when your jobs stop running.

Heroku Scheduler is deceptively simple to set up. Add a command, pick a frequency, done. But there's a critical gap: if your job fails, throws an exception, or simply stops running, Heroku Scheduler says nothing. No alert, no email, no dashboard warning. You find out from a user complaint or a missing report.

This is the same problem shared by every fire-and-forget scheduler. The solution is the same too: the dead man's switch pattern.

What this guide covers:

1 The Heroku Scheduler monitoring gap

Heroku Scheduler runs your command on a dyno, captures its output, and moves on. There are three failure scenarios it does not alert on:

Heroku does provide log drains and you can pipe logs to Papertrail or Datadog. But that still requires you to write a log parser rule for every job — and it won't catch the case where a job simply doesn't fire.

The core issue: Monitoring logs only catches jobs that ran and failed. It does nothing for jobs that didn't run at all. You need a different pattern for that.

2 The dead man's switch pattern

A dead man's switch works in reverse. Instead of your monitoring tool watching for an error, your job sends a "I'm alive" ping to a monitoring service at the end of every successful run. If the ping stops arriving, the monitoring service alerts you.

This catches every failure mode:

The implementation is one line added to the end of your job. If the ping line is reached, the job succeeded.


3 Adding a heartbeat ping to your Heroku Scheduler job

Ruby

# lib/tasks/daily_report.rake
task :daily_report do
  # ... your job logic here ...
  generate_report
  send_emails

  # Heartbeat ping — fires only on successful completion
  require 'net/http'
  Net::HTTP.get(URI('https://cronwatch.ping/YOUR_TOKEN'))
end

Or with the Faraday or HTTParty gem if you already have one in your Gemfile:

HTTParty.get('https://cronwatch.ping/YOUR_TOKEN') rescue nil

The rescue nil ensures a network hiccup doesn't fail your job — the ping is best-effort.

Python

import requests

def daily_report():
    # ... your job logic here ...
    generate_report()
    send_emails()

    # Heartbeat ping — fires only on successful completion
    try:
        requests.get('https://cronwatch.ping/YOUR_TOKEN', timeout=10)
    except Exception:
        pass  # Don't let a network issue fail the job

if __name__ == '__main__':
    daily_report()

Node.js

const https = require('https');

async function dailyReport() {
  // ... your job logic here ...
  await generateReport();
  await sendEmails();

  // Heartbeat ping — fires only on successful completion
  https.get('https://cronwatch.ping/YOUR_TOKEN').on('error', () => {});
}

dailyReport();

Shell / Bash

For Heroku Scheduler tasks that run a shell command directly:

ruby lib/tasks/daily_report.rb && curl -s https://cronwatch.ping/YOUR_TOKEN

The && ensures the curl only runs if the previous command exited 0. If the Ruby script fails, no ping is sent.


4 Grace periods: preventing false alerts

Heroku Scheduler has timing jitter. A job scheduled to run every hour may run at :00, :02, :01, depending on dyno availability. Your monitoring tool needs to account for this with a configurable grace period — typically 10–20 minutes for hourly jobs, and 2–3 hours for daily ones.

Without a grace period, you'll get false alerts every time Heroku is a few minutes slow. With too long a grace period, you'll miss real failures.

Job frequencyRecommended grace period
Every 10 minutes5 minutes
Every hour15 minutes
Every day2 hours

5 What to look for in a Heroku Scheduler monitor

Not all monitoring tools are built for Heroku's fire-and-forget model. Here's what matters:

Tip: Set up monitoring for your most critical Heroku jobs first — billing runs, report generators, data sync jobs. These are the ones where a missed execution has immediate business impact.

Common Heroku Scheduler failure causes

Once you have monitoring in place, you'll start seeing which jobs actually fail. Common causes for Heroku Scheduler jobs:


CronWatch — Dead Man's Switch Monitoring for Heroku Scheduler

CronWatch monitors your Heroku Scheduler jobs with the dead man's switch pattern. Add one line to your job. If it stops firing, you get an alert. Configurable grace periods, email alerts, simple setup.

Join the waitlist → Parse cron expressions free

Related reading