Dead Man's Snitch vs CronRadar: Snitch Intervals and Cron Schedules
Updated
Contents
Dead Man's Snitch is a hosted cron job monitor: each job gets a "snitch," a unique check-in URL, and the service alerts you when that URL isn't requested during the snitch's interval. Intervals are fixed UTC windows from one minute to a month, and by default the check runs when each window closes. CronRadar watches for the same silence but expects each run at the next time of a five-field cron schedule plus a grace period, and it also accepts start, complete, and fail reports. Every Dead Man's Snitch fact below comes from its own site and documentation, checked October 25, 2026.
How Dead Man's Snitch Works#
A Snitch Is a Check-In URL#
Dead Man's Snitch, a product of Collective Idea, calls itself "a monitoring tool for cron, Heroku Scheduler, or any periodic process" (FAQ). A snitch has a name, an interval, an alert type, and alert email addresses, and gets a URL on nosnch.in. The minimal setup appends a request to the job (FAQ):
0 3 * * * /opt/backup.sh && curl https://nosnch.in/c2354d53d2&& checks in only when the job exits 0. Any HTTP client works, and a check-in can carry a message in an m parameter (FAQ). A snitch starts watching after its first check-in; one still pending three days after creation gets you a reminder email (FAQ).
Intervals Are Fixed UTC Windows#
The interval is the snitch's whole notion of a schedule. The API says interval must be one of 1_minute, 2_minute, 3_minute, 5_minute, 10_minute, 15_minute, 30_minute, hourly, 2_hour, 3_hour, 4_hour, 6_hour, 8_hour, 12_hour, daily, weekly ("Monday to Monday"), or monthly, with the sub-hourly values marked "Basic only" (API reference). None of those values is a cron expression. The FAQ's interval table does print one beside each interval, such as 0 0 * * * for Day, but that column restates when the window closes (FAQ).
Windows follow UTC: a day ends at midnight UTC, a week at midnight UTC on Monday, a month at midnight on the 1st. A snitch passes if it checked in at least once during the period. A job that checks in at the start of one period and the end of the next still passes, which the FAQ says is deliberate, because run times vary (FAQ). A job whose frequency isn't on the list should round up to the next interval (FAQ).
Basic and Smart Alerts#
A snitch's alert_type is basic, the default, or smart. Basic "will have a static deadline"; smart "will learn when your snitch checks in, moving the deadline closer so you can be alerted sooner" (API reference). The FAQ calls the default type Heartbeat. With it, you're alerted at the end of each interval that had no check-in; for an hourly snitch, that's around one minute past the hour after the empty period (FAQ).
The difference shows on a daily job that runs at 03:00 UTC. If one run is skipped, a basic daily snitch alerts when that UTC day closes, about 21 hours later. Smart alerts shorten that wait after a few consistent check-ins. The plans page lists Smart Alerts on Surveillance Van; the FAQ and the launch post add that weekly and monthly smart snitches work on all paid plans, with hourly and daily ones on Surveillance Van.
Error Notices and the Field Agent#
A success-only check-in makes a failed run look like a missed one, reported only when the window closes. Error Notices send the exit status in an s parameter, and a non-zero status produces an immediate notice (launch post). The cron guide uses ; so the check-in happens either way (Cron Job Monitoring):
*/5 * * * * /app/backups.sh; curl -s -d s=$? https://nosnch.in/c2354d53d2The Field Agent, dms, is a wrapper binary for Windows, Linux, macOS, FreeBSD, NetBSD, and Solaris. dms TOKEN command runs the command and checks in when it finishes, sending the run time, exit status, the command's output, and the clock time; --exclude-output withholds the output (Field Agent). On Surveillance Van, Field Agent output becomes an error log attached to error notices, linked from Slack and PagerDuty alerts (error logs).
Dead Man's Snitch Pricing#
From the plans page, checked October 25, 2026:
| Plan | Price | Snitches | Listed features |
|---|---|---|---|
| The Lone Snitch | Free | 1 | One snitch |
| Little Birdy | $5 a month | 3 | Basic intervals, API, Field Agent, unlimited team members |
| Private Eye | $19 a month | 100 | Enhanced intervals, API, Field Agent, unlimited team members, integrations |
| Surveillance Van | $49 a month | 300 | Private Eye's features plus Smart Alerts and Error Notices; a 30-day free trial |
The FAQ says the free plan has hourly, daily, weekly, and monthly intervals (FAQ); the plans page doesn't spell out which intervals are enhanced. For on-premise hosting or more jobs, the page says to contact them.
CronRadar's Free plan covers up to 10 active monitors with every alert channel and no card. On Grow, the first 10 active monitors stay free; each further monitor is billed monthly by schedule class, $2 Fast (gap under 5 minutes), $1 Frequent (5 minutes to under an hour), $0.50 Standard (hourly or less often), in arrears on the month's peak, with no tiers, minimum, or monitor limit, and an optional monthly budget that holds new monitors paused. Business is for custom requirements. Runs, retries, and API calls are never billed (pricing).
List prices per month when every job runs hourly or less often:
| Jobs | Smallest Dead Man's Snitch plan that fits | Dead Man's Snitch | CronRadar |
|---|---|---|---|
| 3 | Little Birdy | $5 | $0 (Free) |
| 10 | Private Eye | $19 | $0 (Free) |
| 50 | Private Eye | $19 | $20 (40 × $0.50) |
| 100 | Private Eye | $19 | $45 (90 × $0.50) |
| 300 | Surveillance Van | $49 | $145 (290 × $0.50) |
At 3 and 10 such jobs, CronRadar's list price is lower; at 50, 100, and 300, Dead Man's Snitch's is. Compare the plan that has what you need, though: its plans page lists integrations from Private Eye and Error Notices only on Surveillance Van. Jobs that run more often than hourly cost $1 or $2 each on CronRadar once past the free 10.
How CronRadar Decides a Run Is Late#
A CronRadar monitor has a five-field cron schedule, evaluated in UTC, and a grace period with a 60-second minimum and a 90-second default (schedule syntax). Every check-in moves the expected time to the schedule's next occurrence. An overdue check runs once a minute: past the expected time the monitor is warning, and it turns critical, with an incident, once it is both past the grace period and at least two minutes late. For the 03:00 job with a 900-second grace, a skipped run turns critical after 03:15 UTC.
Lifecycle reports cover more than "it ran" (concepts):
failopens an incident immediately, with an optional message of up to 1,000 characters.startthencompleterecords the run's duration; the monitor keeps the last successful one. There's no slow-run setting.- Stuck runs need a
start. Because every check-in, includingstart, moves the expected time to the next scheduled occurrence, a monitor whose last event is astartwith nocompleteorfailgoescriticalas stuck when that time plus grace passes. The window is per job, not per run: the next run'sstartresets it, so a hang is caught only when the job then goes silent. There's no per-job maximum runtime; a timeout inside the job turns a hang into afail(hanging cron jobs). - Outcomes: a POST to
/completecan carry up to five numeric or boolean values, such asrecords_processed, checked against expectations configured in the automation's settings. A missing or violated value opens an incident, which catches a run that exits 0 without doing its work (silent success). A slow run can be caught the same way by reportingduration_secondsagainst a bound. - Never ran: a monitor created in the dashboard or by framework discovery before the first run stays
pendingand sends a never-executed alert once the first expected run plus grace passes. A monitor created by its first check-in can't flag a job that never runs.
Side-by-Side Facts#
Dead Man's Snitch column checked October 25, 2026. For other tools, see cron monitoring tools compared.
| Question | Dead Man's Snitch | CronRadar |
|---|---|---|
| A run that fails | Error Notice from a non-zero s (Surveillance Van) |
fail check-in, immediate |
| A run that hangs | Never checks in, so it alerts as missing | Stuck, if it sent start; otherwise missed |
| Run data | Field Agent sends run time, exit status, and output | Duration from start/complete; up to five outcome values; no logs collected |
| Ways to check in | HTTP, Field Agent, email, Amazon SNS, Heroku buildpack (docs) | HTTP; .NET SDK; Hangfire and Quartz.NET 3.x discovery |
| Alert destinations | Email; app push on paid plans; ilert, Microsoft Teams, Opsgenie, PagerDuty, Slack, VictorOps, webhooks, filterable by tag (integrations, FAQ) | Email, Slack, webhook, Discord, PagerDuty |
| Repeat alerts | One email per failed period until paused or checked in; one on recovery (FAQ) | First alert, at most one reminder every 24 hours, recovery message (verify) |
| Context on alerts | Snitch notes and tags; notes are in webhook payloads (webhooks) | Owner in every channel, severity in all but email; runbook, logs, and repository URLs in webhook and PagerDuty alerts |
| Managing monitors from code | JSON API: create, tag, pause until a time, delete (API reference) | Check-ins create monitors when they carry a schedule; POST /sync registers jobs in bulk (API reference) |
| History | Two years for all snitches (FAQ) | Free: 30 days of runs, 90 of alerts. Grow: 90 and 180 |
Both tools keep time in UTC (FAQ). CronRadar has no SMS, on-call schedules, or escalation policies; PagerDuty is the hand-off for on-call.
Moving Snitches to CronRadar#
Take the Schedule From the Job, Not the Snitch#
A snitch's interval is often looser than the job, because Dead Man's Snitch tells you to round up. Read the real schedule from the crontab or scheduler, write it in UTC, and size the grace from the job's start delay plus, if it reports only at the end, its run time (choosing a grace period).
| The job (UTC) | Snitch interval | CronRadar schedule |
|---|---|---|
| Every 15 minutes | 15 Minute | */15 * * * * |
| Every hour at :20 | Hour | 20 * * * * |
| Daily at 03:00 | Day | 0 3 * * * |
| Weekdays at 09:00 | Day | 0 9 * * 1-5 |
| Mondays at 01:30 | Week | 30 1 * * 1 |
| The 1st at 04:00 | Month | 0 4 1 * * |
| Every 6 hours at :10 | 6 Hours | 10 */6 * * * |
The weekdays row is where a cron schedule fits better: under the at-least-once-per-period rule, a daily snitch on that job sees an empty window every Saturday and Sunday. CronRadar doesn't accept @daily-style shortcuts or interval schedules, and when both day fields are restricted it expects a run only on dates matching both (schedule syntax).
Jobs That Run Any Time Within a Window#
Some snitches exist because the job's time varies, say an import that starts whenever an upstream file lands, between 03:00 and 09:00 UTC. Since a check-in moves the expected time to the schedule's next occurrence, a report that arrives before the scheduled time leaves that day's occurrence open: with 0 5 * * *, a report at 04:40 sets the expected time to 05:00 the same day, and the monitor goes late after 05:00 plus grace. So set the schedule to the earliest time the job can report, 0 3 * * *, and the grace to cover the spread to the latest report plus the run time and a margin, for example gracePeriod=23400 (six and a half hours). A missed day then turns critical after about 09:30 UTC.
Swap the Snitch URL for a Check-In#
Replace a line like 0 3 * * * /opt/backup.sh; curl -s -d s=$? https://nosnch.in/c2354d53d2 with a wrapper:
0 3 * * * /opt/backup-monitored.shThe wrapper reports start, runs the job, reports complete or fail, and exits with the job's own code. Each report gives up after five seconds and ignores errors, so a monitoring outage can't fail the backup. It reads the key from a file only the job's account can read; the dead man's switch guide explains why not to set it in the crontab:
#!/bin/sh
# /opt/backup-monitored.sh
CRONRADAR_API_KEY=$(cat /etc/cronradar/api-key)
url="https://cron.life/api/v1/ping/nightly-backup"
run_id="nightly-backup-$(date +%s)-$$"
report() {
event=$1
shift
curl --fail --silent --show-error --max-time 5 --output /dev/null \
--request POST --get --user "$CRONRADAR_API_KEY:" \
--data-urlencode "schedule=0 3 * * *" \
--data-urlencode "gracePeriod=900" \
--data-urlencode "run_id=$run_id" \
"$@" "$url/$event" || true
}
report start
/opt/backup.sh
rc=$?
if [ "$rc" -eq 0 ]; then
report complete
else
report fail --data-urlencode "message=backup.sh exited with code $rc"
fi
# The snitch's old check-in, kept for the overlap; delete it afterwards.
curl --silent --max-time 5 --output /dev/null --data "s=$rc" https://nosnch.in/c2354d53d2 || true
exit "$rc"fail replaces the Error Notice, and start adds stuck detection. Because each report carries the schedule, the first run creates the monitor and a deleted monitor is recreated by the next run. schedule and gracePeriod apply only when a check-in creates the monitor; change them later in the monitor's settings. CronRadar has no published command-line agent like dms; this wrapper does that job.
.NET Jobs#
For a .NET console app that cron or Task Scheduler starts, the CronRadar .NET SDK does the wrapping. NuGet installs CronRadar 1.0.13 (checked September 20, 2026) with dotnet add package CronRadar, and it reads CRONRADAR_API_KEY from the environment:
// Program.cs
try
{
// The class shares its namespace's name, so qualify it fully.
await CronRadar.CronRadar.WrapAsync("nightly-report", async () =>
{
// A timeout inside the job turns a hang into a reported failure.
using var http = new HttpClient { Timeout = TimeSpan.FromMinutes(20) };
using var response = await http.PostAsync("http://localhost:8080/internal/reports/nightly", null);
response.EnsureSuccessStatusCode();
}, schedule: "0 3 * * *");
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex);
return 1;
}WrapAsync reports start, then complete or fail, and rethrows the job's exception; its own network errors never reach your code, and each request gives up after 5 seconds.
Hangfire and Quartz.NET 3.x jobs don't need a wrapper each. builder.Services.AddCronRadarHangfire(); after AddHangfire() discovers recurring jobs and monitors each one unless its method has [SkipMonitor] (Hangfire monitoring). The published CronRadar.Hangfire 0.1.0 can report a failure before Hangfire finishes retrying, including cancellations; reporting only after retries are exhausted requires the pending 0.2.1 release. For Quartz.NET 3.x, CronRadar.Quartz 0.1.0 adds await scheduler.MonitorAll(); after the jobs are registered and before Start(), but it monitors only jobs on repeating simple triggers, because it sends a cron trigger's six-field expression unchanged and CronRadar rejects it until the pending 0.1.1; on Quartz.NET 4.x, use WrapAsync inside the job. Outside .NET, each job reports with its own HTTP check-in: no CronRadar SDK is installable today for Node.js, Python, PHP, Ruby, or Go, and none of them gets auto-discovery.
Verify Before Deleting the Snitch#
Keep both running for one normal schedule window. Confirm a real scheduled run reached CronRadar, check the channels and recipients in Alerts, and test delivery with a channel test or a harmless job in a separate test application. Then remove the nosnch.in line and delete the snitch. Leave the scheduler unchanged in the same deployment (migration guide).
Which One Fits#
Dead Man's Snitch Fits Better When#
- "At least once a day" is the real requirement and run times drift; fixed windows tolerate that without tuning.
- The heartbeat comes from something other than a script, such as an Amazon SNS topic or an email.
- Alerts must reach Microsoft Teams, Opsgenie, ilert, VictorOps, or a mobile app, which aren't among CronRadar's five channels.
- You want the job's output attached to error alerts; CronRadar doesn't collect logs, only a link to your log search.
- You need two years of history, or many hourly-or-slower jobs within a fixed plan price.
- You want a packaged wrapper binary, including for FreeBSD, NetBSD, or Solaris.
CronRadar Fits Better When#
- Jobs run at exact times, and a missed run should go critical once its grace period passes, not when a window closes.
- The schedule doesn't map onto an interval, like weekdays only or
0 6,18 * * *. - You want failed, stuck, and outcome-checked runs reported, including on the Free plan.
- You have up to 10 jobs and want Slack, PagerDuty, Discord, or webhook alerts at no cost.
- The jobs are Hangfire jobs, or Quartz.NET 3.x jobs on repeating simple triggers, that you want discovered instead of wired one by one.
Frequently Asked Questions#
What is Dead Man's Snitch?#
Dead Man's Snitch is a hosted service from Collective Idea that alerts you when a cron job or other periodic process stops checking in. Each monitored job gets a snitch, a unique URL the job requests when it runs. Plans range from one free snitch to 300 snitches for $49 a month (checked October 25, 2026).
How does Dead Man's Snitch decide a job is late?#
It divides time into fixed UTC windows of the snitch's interval and checks whether at least one check-in arrived in each. With the default basic alerts, an empty window alerts when it closes, so a daily snitch alerts after midnight UTC. Smart alerts learn when the job usually checks in and move the deadline earlier.
Can Dead Man's Snitch use cron expressions?#
Its API accepts only named intervals, from 1_minute to monthly. The cron expressions in its FAQ describe when each interval's window closes; they aren't schedules you enter. A job with a cron schedule picks the matching interval or rounds up to the next one.
How do I move snitches to CronRadar?#
Take each job's real schedule from its crontab, write it in UTC, and send it with a grace period on the first check-in, which creates the monitor. Replace the nosnch.in request with a start, complete, and fail wrapper, keep the snitch through one real run, test an alert, then delete it.
What does a dead man's switch monitor not catch?#
A plain heartbeat catches a job that stops running, not one that runs and does the wrong thing. A run that exits 0 without doing its work still checks in, a success-only check-in turns a failure into a late missed-run alert, and a hang looks like a missed run. Exit-status reporting, a start signal, and outcome checks cover those cases; the dead man's switch guide explains the basic pattern.
Put this guide to work
Know when the next run is missing
Connect one scheduled job, confirm a real completion, then verify the alert destination. Keep your existing scheduler in charge of running the work.