Sep 20, 2026 · by Michael Sunmisola · View source

Cronhq

Cron jobs that actually run

Cronhq

Editorial analysis

Cronhq and the Quiet Crisis Behind Every Scheduled Post

If you run social media for a living, you already know the two failure modes that keep operators up at night, and neither one announces itself. The first is the double-post: a scheduled carousel goes out twice because two workers grabbed the same queue slot, and your client sees the same Reel in their feed back-to-back. The second is worse — the silent stall. A publishing job quietly stops firing, no error, no alert, and three weeks later someone asks why the content calendar has been empty since the 8th. Cronhq, a solo-built job scheduler that launched on Product Hunt, is aimed squarely at both. It’s a backend tool, not a social platform, but the failure logic it’s solving is the exact logic underneath every “post at 9am across five channels” workflow you’ve ever trusted. That’s the why. Here’s the what, and where I think it lands.

What Cronhq Actually Solves (and Why a Social Team Should Care)

The maker, Michael Sunmisola, frames the origin story around a bug he kept watching teams hit at client gigs: scale an app from one box to two, both boxes carry the same crontab, and the nightly billing job fires twice. A customer gets charged twice. Nobody finds out from a dashboard — they find out from an angry support ticket. The quieter half is a job that just stops. No crash, no alert. Six weeks later the reports have been empty since March.

Strip away the billing framing and that’s the same story as a broken auto-publisher. If you’ve ever used Buffer, Hootsuite, Later, or Metricool to queue a week of content, you’ve been leaning on a scheduler that is, at its core, a cron job with a nicer face. When those tools misfire — and they do — you get one of the two failures above. Cronhq’s pitch is that it makes both structurally hard rather than merely unlikely.

The mechanics, per the maker: every due run is claimed through a Postgres lock row with an expiry deadline, and next_run_at moves forward before dispatch. Two workers can’t fire the same run. If a worker dies holding the lock, the expiry lets another take over instead of the run being lost. That’s the exactly-once claim. On top of that: per-job retries with configurable max attempts, delay, and timeout; alerts that dedup on transitions rather than state (one alert when a job starts failing, one when it recovers — not 47 pages at 3am); signed webhooks using HMAC-SHA256 over timestamp plus body with rotatable per-job secrets; heartbeat monitors as a dead-man’s switch for jobs Cronhq doesn’t run; and cron-as-code via a cronhq.yaml file with npx cronhq sync and npx cronhq tail.

The stack is Rust (axum, sqlx, tokio) with Postgres as the only coordination primitive — no Redis, no Kafka. It’s MIT licensed and self-hostable with one docker-compose, and the self-hosted image is the same image the cloud runs, with no features hidden behind a flag. Free tier is five jobs; paid starts at $5. Those figures come straight from the launch post.

The alert-dedup detail is the one I’d steal first

Of everything in that list, the transition-based alerting is the piece I’d most want every social tool to copy. In my own experience running accounts across Instagram, TikTok, YouTube, X, LinkedIn, Facebook, Threads, and Pinterest, the single biggest reason operators stop trusting their scheduler is notification fatigue. A flaky API handshake with one platform fires forty alerts in an hour, everyone mutes the channel, and then the real outage — the one where nothing posted for two days — goes unseen. Alerting on state transitions instead of raw state is a small design choice with an outsized effect on whether a human actually reads the alert. My take: this is the most transferable idea in the whole product, more than the exactly-once machinery.

Where It Sits Against the Tools You Already Pay For

Let’s be honest about the comparison set. Cronhq is not competing with Buffer or Later on the front end — it has no composer, no media library, no analytics dashboard, no Canva or CapCut integration. It’s competing with the plumbing those tools sit on top of, plus the category of developer schedulers like Celery Beat, Sidekiq, cloud-native options like AWS EventBridge Scheduler, and platform-native cron in GitHub Actions or Vercel Cron Jobs.

Where the incumbents win: Buffer, Hootsuite, Later, and Metricool give you a UI a non-technical social manager can actually use, plus per-platform API handling that’s genuinely hard to replicate — token refresh, rate limits, media format quirks, the whole mess. If your job is publishing content, you want those tools. Full stop.

Where Cronhq’s thesis bites: if you’re an indie founder or a small agency that has stitched together your own posting pipeline — a queue, a worker, a webhook to a platform API — you’re already running a scheduler, and you’re probably running it badly. That’s the gap. The maker’s own framing is that this is for teams who’ve felt the double-charge or the silent stall firsthand. If you’ve never written a cron job, this product is not for you, and I’d say that plainly rather than dress it up.

Why this matters more to certain operators than others

If you’re a solo creator posting manually through the native apps, none of this applies — you don’t have a scheduler to break. If you’re a social media manager using Buffer or Hootsuite as a managed service, the reliability work happens behind their walls and you’ll never see it. The audience that should actually care is the middle layer: indie founders running their own publishing stack, agencies with a custom internal tool, and growth marketers who’ve wired platform APIs directly because the SaaS options didn’t fit a niche workflow. For that group, the exactly-once and heartbeat concepts are directly reusable even if you never adopt Cronhq itself.

What Creators and Social Teams Can Borrow From It

You don’t need to migrate anything to steal the good ideas. Three of them translate cleanly to social operations.

First, treat absence as a first-class signal. Cronhq’s heartbeat monitors exist because, as the maker puts it, “absence is the thing that’s hard to detect.” In social terms: your analytics will happily show you a post that underperformed, but nothing in most dashboards tells you a post didn’t go out. Build a check — even a manual one — that flags missing posts, not just bad ones. A simple daily glance at whether every scheduled slot actually published is worth more than most of the fancy reporting layers.

Second, dedup your alerts. If your team gets pinged on every API hiccup, you’ve trained yourselves to ignore the channel. Transition-based alerting — one on failure, one on recovery — is the pattern to demand from whatever tooling you use, or to build if you’re rolling your own.

Third, version your schedule as code. The cronhq.yaml + npx cronhq sync model means the schedule lives in a file you can review, diff, and roll back, not in a UI where someone silently changes a posting time and nobody notices. If you run a content calendar across multiple clients, having that calendar expressed as a reviewable artifact is a genuine operational upgrade. I’d bet most agencies would benefit from this even without touching Cronhq.

The idempotency lesson hiding in the comments

The most valuable thread on that launch page isn’t the pitch — it’s the pushback. A commenter, Davide Terni, raises the case that exactly-once only covers the scheduler’s side: if the receiving endpoint completes the work but the response is lost or times out, the retry fires again and the charge (or the post) happens twice on the receiver’s side. He notes the docs only expose X-Cronhq-Timestamp and X-Cronhq-Signature, and the timestamp changes on every attempt, so there’s nothing stable to dedupe on. He cites hitting this exact problem with Celery and Redis, where long tasks got redelivered and ran twice.

The maker’s response is refreshingly honest: he confirms there’s no stable execution ID across retries right now, acknowledges the gap, and commits to adding one — a run/execution ID that stays the same for every attempt of a single execution, while each attempt keeps its own metadata. For anyone building a publishing pipeline, that exchange is a free education in why “exactly-once” is a claim about the scheduler, not about your downstream effects. If you’re wiring a custom poster to a platform API, you need your own idempotency key regardless of what your scheduler promises. That’s not a knock on Cronhq — it’s the reality of distributed systems, and the fact that the maker said so publicly is a trust signal.

Where My Judgment Says It Falls Short

I want to be balanced here, because the launch page is a pitch and pitches are selective.

The exactly-once claim deserves scrutiny. The maker himself asks the community whether leading with “exactly-once” is the right call or too in-the-weeds. My take: it’s the right concept to lead with for a backend audience, but the phrase is doing more marketing work than the implementation can fully back until the run-ID gap is closed. True exactly-once delivery is famously hard; what Cronhq appears to offer is exactly-once dispatch with at-least-once retry semantics downstream. That’s a meaningful distinction and the docs should say it plainly.

The SSH/CLI gap is real. A commenter, Jay Janarthanan, asks whether all his code has to expose a webhook, and suggests direct SSH execution like ssh -T user@remote-ip 'python3 /path/to/script.py'. The maker confirms there’s a CLI option so you don’t have to wrap everything in HTTP, but concedes direct SSH execution is “interesting” and something he’ll look into. For a lot of small operators, the ability to just run a remote script is the whole ballgame, and it’s not there yet.

Who this is NOT for: anyone who wants a visual content calendar, a media library, or per-platform publishing handled for them. Cronhq is infrastructure. If you don’t have engineers or don’t want to think about webhooks and YAML, this will feel like being handed a wrench when you wanted a car.

Open questions the source doesn’t answer: pricing above the $5 entry tier is not disclosed. Uptime, SLA, and support commitments are not disclosed. How the cloud offering handles multi-region or high-volume scenarios isn’t covered. And the run-ID feature the maker committed to is, as of the launch thread, still planned rather than shipped.

The crash-window nuance worth understanding

There’s a good exchange between the maker and Gal Dayan about what happens when a worker dies mid-job. The maker explains the lock is tied to the DB session/transaction, so if the worker dies and the connection drops, Postgres releases it automatically — the heartbeat isn’t what clears the lock. But he flags the harder case: the window where the target endpoint completed the work but Cronhq never recorded the success. That’s the ambiguous-completion case, and as Dayan notes, it’s scarier than a double-run because nothing looks broken. This is the exact scenario a social poster hits when a platform API accepts a post but the response times out — the post went live, the scheduler thinks it failed, and it retries. If you take one thing from this whole launch, take that: your publishing pipeline needs its own dedupe key, independent of any scheduler’s promises.

What I’d Watch / Test Next

If you run social operations and this resonates, here’s what I’d actually do this week — no migration required.

First, audit your current publishing flow for the ambiguous-completion case. Pick your most reliable-looking scheduled post from the last month and ask: if the platform API had accepted it but the response was lost, would anything have caught the duplicate? If the answer is no, you’ve found a real gap, and it exists whether you use Buffer, a custom script, or anything else.

Second, build a missing-post check. One daily review of whether every scheduled slot actually published — even a manual one — closes the silent-stall failure mode that no analytics dashboard surfaces.

Third, if you’re technical, watch Cronhq’s run-ID rollout. The maker committed to shipping a stable execution ID across retries, and once that lands, the idempotency story gets materially stronger. That’s the feature that would make me comfortable recommending it for anything touching money or irreversible actions. Until then, I’d treat it as a promising, honestly-documented tool from a solo builder who’s engaging seriously with hard feedback — which, in a category full of overpromising, is itself worth something. Test it on non-critical jobs first, keep your own dedupe layer, and read the docs before you trust it with anything you can’t un-send.

Ready to Create Your Own?

Join thousands of brands creating high-performing video ads with FLOWNIB. No editing skills required.

Start Creating for Free