Comparison · vs Cronitor

RunWisp vs Cronitor: monitor the job, or run it and monitor it?

Cronitor is a hosted monitor: your jobs report in, and it alerts when they fail, run long or go quiet. RunWisp is a self-hosted runner: it starts the job itself, so the result is recorded without anything reporting in. Different jobs, and they combine well.

Verdict

Should you switch?

The 10-second version. Skim, decide, scroll down for the receipts.

Use RunWisp if

  • Your Cronitor bill grows with every cron job you add.
  • Run times, exit codes and job output shouldn't leave your server.
  • You want retries, timeouts and overlap rules applied, not only reported.
  • The box is air-gapped or behind strict egress rules.
  • You'd rather keep schedule and alert rules together in a file in git.
  • You also have long-running services to keep alive.

Keep Cronitor if

  • You need to hear about a server that died. Only an outside monitor can tell you.
  • Jobs run across many hosts and Kubernetes, and you want one dashboard for all of them.
  • You use PagerDuty, Opsgenie or SMS on-call, team roles and SSO.
  • You also want uptime checks and public status pages from the same vendor.
  • Your jobs run in places you can't install a daemon: managed platforms, Sidekiq, Airflow.
Head to head

Yes / no, at a glance

Yes / no — and both columns win on something.

Capability Cronitor RunWisp
Schedules and runs the job ✗cron still schedules ✓
Exit code + duration per run ✓via cronitor exec ✓
Captured output ✓uploaded to Cronitor ✓stays on the box
Retries / timeouts / overlap policy ✗reports only ✓
Failure alerts ✓11 integrations + SMS ✓8 channels + inbox
Alerts when the whole host dies ✓ ✗pair with a heartbeat
Duration / “ran too long” alerts ✓assertions ~timeout fails the run
One dashboard across hosts + Kubernetes ✓ ✗one daemon per host
Uptime checks + status pages ✓ ~curl task, no status page
Teams, roles, SSO ✓Business ✗one password
Self-hosted; data stays on your box ✗ ✓local SQLite
Works with no outbound internet ✗ ✓
Free with no job limit ~5 monitors free, then $2 each ✓
Config as code in git ~API / CLI sync ✓runwisp.toml
Long-running services ✗ ✓
Trade-offs

Pros & cons

What Cronitor does better

  • Watches from outside, so a dead server, a stopped crond or a lost network is caught like any other failure.
  • One dashboard for jobs on every host, in Kubernetes (a Helm chart watches every CronJob), and in Sidekiq, Airflow or ActiveJob through SDKs.
  • Duration assertions, failure tolerance and follow-up alerts, tuned per monitor.
  • Eleven integrations, SMS, PagerDuty and Opsgenie, plus team roles and SAML SSO on Business.
  • Uptime checks and status pages in the same product.
  • Nothing to keep alive on your side: it's someone else's pager at 3am.

What RunWisp adds

  • Runs the job instead of watching it. No wrapper, no API key on every host, no step between cron and the report.
  • timeout, retry_attempts, on_overlap and catch_up act on the job. A monitor can only tell you they were needed.
  • Output, run times and exit codes stay in SQLite on the box. Nothing about your jobs goes to a third party.
  • Works fully offline, so it fits air-gapped and on-prem machines.
  • Free and GPL-3.0, with no per-job price. Fifty jobs cost the same as five.
  • Schedule, policy and alerts in one TOML file you review in a pull request.
  • A Run button, live logs, and a TUI over SSH to re-run the fix from where you noticed the failure.
  • Supervises long-running services in the same file.
The simple case

The simple case

A nightly backup. On the left, cron starts it and cronitor exec reports the outcome to Cronitor. On the right, RunWisp starts it and keeps the outcome itself.

crontab + cronitor exec
# crontab, after "cronitor sync" wrapped the line
0 3 * * *  cronitor exec nightly-backup /usr/local/bin/backup.sh
runwisp.toml
# runwisp.toml: the daemon runs it and records the result
[tasks.nightly-backup]
cron   = "0 3 * * *"
notify = ["slack-ops"]
run    = "/usr/local/bin/backup.sh"
Production-grade

The version that runs in prod

Three jobs, hardened. On the left, every line is wrapped and the rules live in the Cronitor dashboard. On the right, retries and timeouts are fields in the same file as the schedule. Add one heartbeat task to an outside monitor if a dead host is part of your threat model.

crontab + Cronitor (production)
# crontab: cron schedules, cronitor exec reports
CRONITOR_API_KEY=<key>
0 3 * * *    cronitor exec nightly-backup timeout 55m /usr/local/bin/backup.sh
*/5 * * * *  cronitor exec api-probe curl -fsS https://api.example.com/health
0 4 * * 0    cronitor exec tmp-cleanup find /tmp -mtime +7 -delete

# Grace period, duration assertions, failure tolerance and
# alert routing are set per monitor in the Cronitor dashboard.
runwisp.toml (production)
# runwisp.toml: schedule, policy and alerts in one file;
# one external heartbeat watches the box itself.
[defaults]
notify = ["slack-ops"]

[tasks.nightly-backup]
cron           = "0 3 * * *"
on_overlap     = "skip"
timeout        = "55m"
retry_attempts = 2
retry_backoff  = "exponential"
keep_runs      = 60
run            = "/usr/local/bin/backup.sh"

[tasks.api-probe]
cron           = "*/5 * * * *"
catch_up       = 0
timeout        = "30s"
retry_attempts = 2
run            = "curl -fsS https://api.example.com/health"

[tasks.tmp-cleanup]
cron = "0 4 * * 0"
run  = "find /tmp -mtime +7 -delete"
Migration

Migration cheat sheet

Cronitor concepts on the left, runwisp.toml on the right. A dead-host alert is the one thing to keep outside.

Cronitor RunWisp
cronitor exec <key> cmd run = "cmd", no wrapper
cronitor sync / discover crontab -l | runwisp import cron
Monitor schedule + timezone cron = + timezone =
Grace period / duration assertion timeout = "55m"; an overrun fails the run and alerts
Failure tolerance retry_attempts + retry_backoff: the job is tried again, not just tolerated
Follow-up alerts during an outage Repeats grouped inside coalesce_window (default 1h)
Slack / Discord / Telegram / webhook integration [notifiers.*] + notify = [...]
Output uploaded to Cronitor Full stdout/stderr per run, kept locally
Missing-run alert for a dead host Keep an outside heartbeat: one task that pings Cronitor or Healthchecks.io
Gotchas

Gotchas

A runner can't report its own death

RunWisp catches failed runs, timeouts, crashes and firings missed while the daemon was down. If the whole machine goes dark, nothing on it is left to send the alert. Keep one external heartbeat: a five-minute RunWisp task that curls a Cronitor or Healthchecks.io ping URL. One monitor for the box instead of one per job fits inside Cronitor's free tier.

Your job data stays home

With a hosted monitor, when your jobs run, how long they took and what they printed sit on someone else's servers. RunWisp keeps all of it in a SQLite file on the box. For on-prem, regulated or air-gapped setups that can decide the question on its own.

No cross-host dashboard

RunWisp is one daemon per machine, each with its own UI. With ten servers you have ten dashboards and ten sets of alerts, which still arrive in one Slack channel. If one view over many hosts and Kubernetes is the point, Cronitor does that and RunWisp doesn't.

Run both during the switch

Move a job into runwisp.toml and keep the cronitor exec wrapper in its run line for a week. Both histories should agree. Then drop the wrapper and pause the monitor.

FAQ

FAQ

What is a self-hosted alternative to Cronitor?
It depends on which half you want. For a self-hosted heartbeat monitor, Healthchecks.io is open source and has an official Docker image. If you'd rather stop wiring monitors to cron at all, RunWisp is an open-source cron replacement that ships as a single binary: it runs the jobs, records every run's exit code and output, and sends failure alerts itself. It can't tell you its own server died, so pair it with one external heartbeat.
Does Cronitor run cron jobs?
No. Cronitor monitors jobs that something else schedules. cronitor exec starts the command and reports its result, but cron, systemd or Kubernetes decides when it runs. The CLI's dashboard can edit crontabs and trigger a run, and still needs a cron daemon for scheduled runs.
How much does Cronitor cost compared to RunWisp?
Cronitor's free Hacker plan covers 5 monitors and 1 user. Business is $2 per monitor per month plus $5 per user. RunWisp is free to self-host under GPL-3.0 with no limit on jobs; you run it on hardware you already have and maintain it yourself.
Can RunWisp and Cronitor work together?
Yes. The cheapest useful setup is one Cronitor heartbeat monitor per server, fed by a RunWisp task that pings it every five minutes. RunWisp reports each job; Cronitor reports when the server stops reporting at all. You can also leave cronitor exec in front of individual jobs' run commands if you want them in Cronitor's dashboard too.
Does RunWisp have uptime monitoring?
Not as a product feature. You can schedule a curl health check as a task, with retries, a timeout and grouped alerts, and RunWisp supervises its own services with health_check. It has no public status pages and no checks from multiple regions; Cronitor does both.
Where does job output go?
With cronitor exec, the last 1,000 bytes go into the ping and the full output is uploaded to Cronitor as a log, unless you pass --no-stdout. With RunWisp, stdout and stderr are written to the local data directory and shown in the Web UI and TUI. Nothing leaves the machine unless a notifier sends a failure's last lines to your chat.
Get started
GPL 3.0 · no accounts · free to self-host

Stop paying per cron job to find out it failed.

Install the binary, import your crontab, and keep one heartbeat for the box. Every run lands with its exit code, duration and output in your own dashboard.

Install in 30 seconds
curl -fsSL https://get.runwisp.com | sh