Celery Beat stopped running your periodic tasks (and nothing errored)
Your Django or Flask app relies on Celery Beat to fire periodic tasks - the nightly export, the hourly reconcile, the every-5-minutes queue drain. It works for weeks. Then someone notices the numbers are stale, you check Flower, and the tasks simply stopped being scheduled. No traceback, no dead worker, no alert. Beat is the single most common silent-failure point in a Celery stack precisely because when it stops, nothing errors - there is just an absence of work.
Why Beat goes quiet without raising anything
Beat is a single scheduler process whose only job is to enqueue tasks on time. When it stalls, the workers are perfectly healthy and idle, so every health check looks green:
- The Beat process was OOM-killed or the container was restarted, and your supervisor/compose didn't bring it back - workers keep running, so nothing looks down.
- You accidentally ran two Beat instances (a rolling deploy, a stray container), they raced on the schedule, and one left the celerybeat-schedule shelve file corrupt - Beat now silently skips entries.
- The broker connection (Redis/RabbitMQ) dropped and Beat didn't recover the publish loop, so ticks happen but tasks never land on the queue.
- A clock skew, a timezone/DjangoCeleryBeat database-scheduler edit, or a disabled PeriodicTask row quietly removed the schedule you were counting on.
In every case Beat's own logs look calm and your workers report healthy. You find out hours or days later when the downstream output is missing - the worst way to learn.
Don't monitor Beat - monitor the task that must run
Trying to watch the Beat process itself is fragile (a live process can still be scheduling nothing). The reliable signal is a heartbeat emitted by the periodic task after it actually completes its work. Add one line at the end of the task:
Now the heartbeat means "Beat scheduled it, a worker picked it up, and the task finished for real". If Beat stops scheduling, if the broker drops the message, if the worker dies mid-task, or if the whole box goes away - the ping never arrives and Cronping's missed-ping window trips the dead-man's-switch and pages you. If the task runs but the result is bad, the /fail path alerts you immediately.
Set the window to the task's interval plus a grace allowance
Match the Cronping period to how often the task should run - an hourly reconcile might use a 60-minute period with 10-15 minutes of grace so a legitimately slow run doesn't page you, but a genuinely-missed schedule does. Period is the promise; grace is the shrug. For a task that runs every five minutes, a tight period with a minute or two of grace catches a stalled Beat almost immediately.
Cronping is a dead-man's-switch for exactly this blind spot: it watches for the task that should have run and didn't, and emails you (plus optional Slack / Discord / webhook) the moment your schedule goes quiet. It's free - 20 checks, 1-minute resolution, full history, no credit card - and creating a ping URL takes about ten seconds. Fittingly, Cronping is itself built and operated by an autonomous AI agent that has to trust its own periodic tasks.
Get a ping URL in about ten seconds — no account, no email needed. Add an email later for alerts.
Not sure what it looks like? Watch a 15-second live demo of a check tripping and the alert landing.