Launched this week

Cronhq
Cron jobs that actually run
78 followers
Cron jobs that actually run
78 followers
Cron jobs fail in silence. Two servers run the same crontab and your billing job fires twice. A job dies and nobody notices for weeks. Cronhq is a scheduler built around one guarantee: exactly-once execution, enforced by Postgres locks — not best-effort. Around it: retries with backoff, HMAC-signed webhooks, heartbeat monitors for jobs we don't run, and alerts that fire once on failure and once on recovery. Rust on Postgres. MIT-licensed, self-hostable, same image we run. Free tier: 5 jobs.







Cronhq
@michael_sunmisola To your second question: before trusting it with a job that moves money, I'd look for a run ID in the webhook headers.
Exactly-once covers your side. If two workers never fire the same slot, fine. Instead retries are a different story though: if my endpoint does the work and the response gets lost or times out, you call me again and the charge happens twice on my side. In the docs I only see X-Cronhq-Timestamp and X-Cronhq-Signature, and I guess the timestamp changes on every attempt, so I have nothing to dedupe on.
I hit this with Celery and Redis: long tasks got redelivered, ran twice, and I had to build the guard myself.
Is there an execution ID that stays the same across the retries of one run? Or is it planned?
Cronhq
So all my code has to expose a webhook ? Love to see support for some thing like this
Cronhq
This is very useful. This has been a bugbear of mine for a long time. Well done.
Cronhq
Dial
the "job runs twice" framing is exactly the failure mode that's easy to ignore until it hits a billing job specifically. Curious how the Postgres lock holds up under a worker crash mid-job - does the lock get released automatically so the next scheduled run can pick it up, or does a dead worker leave a job stuck until someone notices via the heartbeat alert?
Cronhq
Dial
@michael_sunmisola that split makes sense, the lock question was really "does it double run" and the honest answer is that's the smaller risk, the ambiguous-completion case is the scary one because nothing looks broken. is the run ID something CronHQ generates and passes to the endpoint so the endpoint itself can dedupe on it, or is it purely internal bookkeeping on your side right now? if it's the former that would let people build idempotency into the receiving job rather than trusting CronHQ's own retry logic alone.
Cronhq
Dial
@michael_sunmisola that's the right fix, and exposing it in the headers rather than keeping it internal is what actually lets people opt into real idempotency instead of just trusting the retry logic. one thing worth thinking through before it ships: will the header be additive (new header, old ones untouched) or will you be changing what X-Cronhq-Timestamp means, since anyone who already built a workaround off the existing headers would need a heads up either way. appreciate you thinking out loud about this in public, it's a good sign for how the product gets built.