What Shipped in the Celery 5.7 Pre-Releases
Celery published 5.7.0a1 on 22 September 2026 and 5.7.0b1 on 6 October. Both are pre-releases on PyPI. Stable is still 5.6.3, from March.
Two things in these releases matter if you run periodic tasks. Beat can finally answer a health probe. And the changelog fixes several ways Beat sent tasks late, or never, while looking healthy.
The New Beat Health Check
Until now a beat process gave you one signal: the PID existed. Pull request #10422, merged on 30 September and shipped in 5.7.0b1, adds an opt-in remote control node to beat.
Enabling Remote Control on Beat
Set beat_enable_remote_control, or pass the CLI flag. Beat joins the control exchange your workers already use, as a node called celerybeat@hostname:
celery -A proj beat --enable-remote-control -n celerybeat@$(hostname)
celery -A proj inspect ping -t 5 -d celerybeat@$(hostname)
# -> celerybeat@example.com: OK
# pong
Beat answers ping and ignores every other broadcast command. It works on the RabbitMQ and Redis transports. A beat embedded in a worker with -B gets no control node, since the worker already answers for that process.
The Tick-Age Rule
The control node runs in its own thread. By itself, a reply would only prove that thread is alive and can reach the broker. So beat stops answering once the scheduler has gone beat_remote_control_max_tick_age seconds without completing a pass. The default is twice the loop interval the scheduler settled on.
A wedged beat that stopped ticking now fails the probe. Before 5.7, a PID check would have called it healthy.
Using It as a Kubernetes Probe
The periodic-tasks guide ships a liveness example:
livenessProbe:
exec:
command:
- /bin/sh
- -c
- celery -A proj inspect ping -t 10 -d celerybeat@$(hostname)
initialDelaySeconds: 60
periodSeconds: 60
failureThreshold: 5
The probe goes through the broker. Restart Redis and every beat probe fails at once. The pull request warns this can turn a liveness probe into a restart storm, hence the generous thresholds. A readiness probe restarts nothing. It gates rollouts and shows status in kubectl get pods. Pick one on purpose, and measure how long your broker actually takes to come back before you set failureThreshold.
The Bugs the Probe Would Not Have Caught
Each fix below describes a beat that was running, connected and ticking.
A Due Task Stuck Behind One That Asked to Wait
Pull request #10468 fixed issue #7649. Beat keeps its entries in a heap. When the entry on top returned "not due, retry later" from is_due(), it stayed on top for good, and the due entries underneath never got a turn.
The loop kept turning the whole time. Passes complete, so the tick-age rule is satisfied. The probe answers pong and the tasks never run.
Beat Sleeping Through a Due Task
Pull request #10558: after is_due() changed the heap, Scheduler.tick() computed its next sleep from a stale timestamp. Beat could doze for up to its maximum interval, five minutes by default, with a task already due.
A Custom Clock Lost on Every Sync
Pull request #10563 closed issue #8790. PersistentScheduler dropped a crontab's custom nowfun after repeated sync and pickle cycles. Your schedule was right after a restart and wrong some cycles later. No error.
DST Arithmetic on Wall-Clock Time
The 5.7.0a1 changelog lists handling for DST gaps in make_aware. Pull request #10769 in 5.7.0b1 goes deeper: countdowns, expirations and beat intervals were computed on wall-clock time. The pull request's Europe/Paris example has ten real seconds passing across the autumn fall-back while beat decides a ten-second interval still has about an hour left.
Europe falls back on 25 October, the US on 1 November. If beat runs in a local timezone with short intervals, that is your next exposure, and the fix is only in a beta. More on the general problem in Time Zone Changes Are Moving When Your Cron Jobs Run.
What a Pong Actually Proves
A reply from celerybeat@host says the process is up, it reaches the broker, and its scheduler loop finished a pass recently. That catches a crash or a hang. Good.
It says nothing about whether the right entry was due, whether the message landed on the right queue, or whether a worker ran it to completion. All four bugs above sit in that gap. So does most of what we listed in our earlier post on Celery Beat.
Checking the Pipeline With a Canary Task
The cheapest end-to-end check for beat is an entry that does nothing except report in:
import requests
from celery import shared_task
from proj.celery import app
app.conf.beat_schedule["beat-canary"] = {
"task": "ops.beat_canary",
"schedule": 300.0,
"options": {"queue": "default"},
}
@shared_task(name="ops.beat_canary")
def beat_canary():
requests.get("https://cronguard.app/api/ping/beat-canary", timeout=5)
Put a dead man's switch on that URL with a ten-minute window. Route the canary to the same queue as your real periodic tasks, so a missing worker on that queue trips it too. When the check-ins stop, something between scheduler and worker broke.
A canary proves the pipeline moves. Whether last night's export succeeded is a different question, and only a check-in at the end of that task answers it.
Frequently asked questions about the Celery 5.7 Beat health check
Is the Celery Beat health check available in a stable release? Not yet. Remote control for beat shipped in Celery 5.7.0b1 on 6 October 2026, which is a pre-release. The current stable release is 5.6.3.
How do I make celery beat answer inspect ping? Set beat_enable_remote_control or start beat with the --enable-remote-control flag and a node name such as celerybeat@ plus the hostname. Beat then answers only the ping command. It works on RabbitMQ and Redis, and not for beat embedded in a worker with -B.
Does a successful ping mean my periodic tasks are running? No. A reply proves the beat process is up, can reach the broker, and has completed a scheduler pass within the tick-age limit. It says nothing about whether a task landed on the right queue or whether a worker ran it to completion.
Should I use the beat ping as a liveness or a readiness probe? The probe goes through the broker, so a broker restart fails every beat probe at once and a liveness probe can turn that into a restart storm. If you use liveness, keep the documented 60-second initial delay and five allowed failures. A readiness probe gates rollouts without restarting anything.
Which Beat bugs does Celery 5.7 fix? A heap entry that asked to retry later could block every other due task, beat could oversleep by up to its maximum interval, PersistentScheduler lost a crontab's custom nowfun after repeated syncs, and intervals used wall-clock time across daylight saving changes. In each case beat kept running and looked healthy.
Further reading
- Celery Beat: The Scheduler Your Django App Is Running With No Safety Net
- Dead Man's Switch Monitoring: The Only Reliable Way to Watch Cron Jobs
- Time Zone Changes Are Moving When Your Cron Jobs Run
Conclusion: Turn the beat ping on when 5.7 goes stable. It is the first probe that can tell a dead scheduler from a live one. Just do not mistake it for proof that anything ran. The same releases that added it fixed a heap that starved due tasks for good, and a beat stuck on that bug would have kept answering pong. Your check-ins at the end of each task are still the alert that fires.
Sources: Celery 5.7.0b1 release notes, Celery 5.7.0a1 release notes, Celery periodic tasks guide, celery/celery pull request 10422.