SteelreedSteelreed

Know the moment a cron job stops running.

Open-source monitoring for cron jobs, scheduled tasks and background workers. Add one line to a job. When it misses a run, fails or runs too long, you get a message on Telegram, Slack or email.

Cronbell

Checks every schedule every 15 seconds.

crontabbilling-1
0 2 * * *  ./close-month.sh \
  && curl -fsS $PING_URL
Spring Bootfound automatically
@Scheduled(cron = "0 0 3 * * *")
void backupInvoices() { … }
Telegram · #opsWAITING

close-month is due at 02:00. Grace period 10 min.

close-month missed its 02:00 run. Last success Oct 9, 38 s.

close-month is back. Ran at 02:14 in 38 s.

Fourteen nights of one job.

Each bar is one run and its height is how long it took. When tonight's run does not show up within the grace period, the job turns red and you get one message. When it runs again, you get one more.

billing · close-month 0 2 * * * · Asia/Ho_Chi_Minh UP
due 02:00 · waiting
Telegram · #ops

close-month missed its 02:00 run. Last success Oct 9 at 02:00, 38 s.

close-month is back up. Ran at 02:14 and finished in 38 s.

Add one line to the job you already have.

Each job gets its own ping URL. The job calls it when it finishes, or calls /start and /fail too if you want durations and errors. When a ping does not arrive on schedule, you hear about it.

  • Nothing to install where the job runs. If it can make an HTTP request, it works.
  • Schedules are real cron expressions with a time zone, so a 02:00 job in Vietnam time is checked at 02:00 Vietnam time.
  • Already on Healthchecks.io? The ping URLs have the same shape. Change the host and you are done.
# Nightly backup, then tell Cronbell it worked
0 2 * * *  /opt/backup.sh && \
           curl -fsS -m 10 --retry 3 https://cronbell.example.com/ping/5b1f0c2e

Four ways a job goes wrong, and what you see.

Every alert says which job, what happened, when it was expected in the job's own time zone, and the last thing it printed.

  1. MISSED

    close-month · no ping within 10 min of the 02:00 run

    The job never started: a deploy dropped the schedule, the server was down, or a lock was left behind.

  2. FAILED

    db-backup · exit 1 · pg_dump: connection to server failed

    The job ran and reported an error. The last lines of its output come with the alert.

  3. RUNNING TOO LONG

    sync-shopee-orders · started 03:00, still running after 45 min

    The job started and never finished. Nothing failed, so nothing else would have told you.

  4. RECOVERED

    close-month · ran at 02:14, finished in 38 s

    One message when it breaks and one when it is fixed. No reminder every minute.

Every job, its schedule and its last run on one screen.

A preview of the dashboard we are building. The bars show how long the last runs took, so a job that is slowly getting slower stands out before it breaks.

Production6 jobs1 down1 paused
JobScheduleLast runNext dueDuration, last 12Status
close-monthbilling-api0 2 * * *Oct 9, 02:00 · 38 soverdue 10 minDOWN
db-backupops · pg_dump to S30 3 * * *Oct 10, 03:00 · 4 m 12 sOct 11, 03:00UP
sync-shopee-orders-and-refunds-for-all-storesworker · every 15 min*/15 * * * *10:45 · 1 m 03 s11:00UP
InvoiceJob.sendRemindersSpring @Scheduled · found automatically0 0 9 * * MON-FRIOct 10, 09:00 · 6 sOct 13, 09:00UP
renew-certificatescertbot · weekly0 4 * * 0—Oct 12, 04:00no runs yetNEW
cleanup-temp-filespaused during migration0 * * * *Oct 7, 13:00 · 2 s—pausedPAUSED

Running on your own server in a minute.

One container, one port. It stores everything in a single SQLite file by default and switches to PostgreSQL when you set a database URL. Your job names, schedules and logs never leave your network.

  • Free and complete. Nothing is held back for the cloud version.
  • Fits on a small VPS: the goal is under 300 MB of memory for 1,000 jobs.
  • Images for amd64 and arm64, so a Raspberry Pi works too.
docker run -d --name cronbell \
  -p 8080:8080 \
  -v cronbell-data:/data \
  ghcr.io/steelreed/cronbell

On Spring Boot, it finds your jobs for you.

Add the starter and set one key. At startup it registers every @Scheduled, Quartz and ShedLock job with its real schedule, and reports every run with its duration and exception. You do not touch the job code.

Reporting runs in the background with a bounded queue. If the monitor is unreachable, your jobs carry on as if it were not there.

InvoiceJob.java
@Component
class InvoiceJob {

  // Found at startup as "InvoiceJob.sendReminders",
  // schedule 0 0 9 * * MON-FRI, Asia/Ho_Chi_Minh
  @Scheduled(cron = "0 0 9 * * MON-FRI", zone = "Asia/Ho_Chi_Minh")
  void sendReminders() {
    invoices.overdue().forEach(mailer::remind);
  }
}

# application.yml
cronbell:
  url: https://cronbell.example.com
  key: ${CRONBELL_KEY}

How it compares.

Good tools already exist, and some are open source too. Prices are from their websites in October 2026.

ToolOpen sourceSelf-hostedCron schedules with time zonesRun durations and errorsAlerts when a job never ranFinds Spring jobs without code changes
CronbellFree self-hosted · cloud ~$9/mo planned
Healthchecks.io20 checks free · $20/mo for 100
Cronitor$2 per monitor + $5 per user /moSDK, add calls by hand
Uptime KumaFreeinterval heartbeat only
Sentry Crons$0.78 per monitor /mosource-availablewith all of Sentryannotate each job
A script that emails youFree——only if it runs

Cronbell is in development: its row describes what the first release is built to do. Spotted something wrong about another tool? Tell us at hello@steelreed.com and we will fix it.

Free to run yourself. Cheap when we run it.

The cloud plans are planned prices for launch and may still change. People who sign up for early access get the first months of Team free.

Self-hosted

$0

On your server, for as long as you like.

  • Unlimited jobs and members
  • Every alert channel
  • History as long as you keep it
  • Help through GitHub issues

Cloud Free

$0

For side projects and small servers.

  • 20 jobs
  • Email and Telegram
  • 30 days of history
  • 1 member

Cloud Team

$9/month

For a team that runs production jobs.

  • 200 jobs
  • Slack, webhooks, and Zalo later
  • 1 year of history and duration trends
  • 10 members, email support

Get early access.

The first build goes to people on this list, for self-hosting or on the cloud. Tell us how you run scheduled jobs today and we will shape the first version around it.

We only email you about the first build. No newsletter, and we never share your address.

Questions

Can I use it today?

Not yet. It is in development and the first build goes to the early access list. The source code goes public on GitHub with that build.

How is it different from Healthchecks.io?

Healthchecks.io is excellent and open source too, and we use the same ping URL shape so moving is easy. We focus on three things: self-hosting with one Docker command and SQLite, a dashboard that shows duration trends, and a Spring Boot starter that finds jobs without code changes.

What happens if the monitor itself goes down?

Your jobs keep running: a ping that fails is ignored by the job. When the monitor comes back it does not alert for runs it could not see while it was down. On the cloud we watch the monitor from a separate provider.

Which licence is it under?

The server and dashboard are AGPL-3.0. The Spring Boot starter and client libraries are Apache-2.0, so adding them never changes the licence of your application.

Who builds it?

Steelreed, a small studio in Vietnam. We also make QueryFence, which checks the SQL your tests send to the database.