★ 28,574PythonNOASSERTIONupdated Jun 2026
best for the default choice — broadest ecosystem, most integrations, most battle-tested
Celery is the one your colleagues already know. Ten-plus years as the default Python answer to background jobs means broker and backend support most of the others can't match — RabbitMQ, Redis, SQS, and Pub/Sub for transport, half a dozen options for results — plus canvas primitives (chains, groups, chords) for when one task needs to kick off three more.
That history comes at a cost. celery/app/defaults.py runs to hundreds of settings, and the docs don't always explain which ones interact, so a misconfigured deployment usually means guesswork. The default prefork pool forks OS processes, which plays badly with Django's database connections — a well-known source of stale-connection bugs that catches teams every year. And unlike everything else here, Celery's README says outright that Windows isn't a supported target.
If you just want enqueue-a-function-call without the weight, RQ is the smaller Python option below — Celery earns its complexity on real fanout or multiple brokers, but it's not where you start a small project.
Our full take →GitHub ↗
★ 13,535RubyNOASSERTIONupdated Jun 2026
best for Ruby/Rails teams — the de facto standard there
Sidekiq is to Ruby what Celery is to Python — if you're on Rails, this is barely a decision. Threads instead of forked processes give it real throughput (23k jobs/sec on MRI, more under YJIT), and the middleware chain is a clean place to hang instrumentation without monkey-patching core classes.
The catch is Redis: it's not just a dependency, it's the only state your jobs have, so Redis going down means your queue is gone, not just stalled — there's no SQL-backed fallback the way Hangfire or River offer in their own ecosystems. And the features you'll actually want in production — cron, batches, rate limiting — live behind Sidekiq Pro or Enterprise, a paywall you'll hit faster than the marketing suggests, much like how BullMQ holds job groups and batching behind BullMQ-Pro.
Going through ActiveJob for Rails convenience costs roughly 2x throughput versus writing Sidekiq::Job directly — worth knowing before you assume the integration is free.
Our full take →GitHub ↗
★ 10,078C#NOASSERTIONupdated May 2026
best for .NET teams who want jobs running inside the web app, no separate worker process
Hangfire's pitch is specific: no separate worker process, no extra service to deploy — jobs run inside the ASP.NET app you already have, with a dashboard thrown in for free. That's a real advantage over Celery or Sidekiq, which assume you're standing up dedicated workers from day one.
It's also where the simplicity ends. SQL Server storage polls the jobs table rather than getting pushed to, which is fine until you're at a scale where River's or BullMQ's event-driven backends don't carry that tax. The dashboard ships with no real authentication — just a filter that blocks non-local requests — and it's easy to expose job internals through a misconfigured proxy. Before adopting it somewhere with a legal review process, know the LGPL license comes with separate commercial and royalty-free license files, a murkier story than the MIT terms on most of the rest of this list.
Recurring jobs are CRON-only too, so anything needing 'run N minutes after the last run finished' semantics means writing DisableConcurrentExecution guards yourself.
Our full take →GitHub ↗
★ 9,000TypeScriptMITupdated Jun 2026
best for Node.js/TypeScript teams already running Redis
BullMQ is the Node default for the same reason Sidekiq is Ruby's — it's Redis-backed, it's fast, and everything that matters (state transitions, rate limiting, stalled-job detection) runs as atomic Lua scripts so two workers can't race on the same job. The FlowProducer API for parent/child dependencies is genuinely useful for DAG-style pipelines, something only River and Hatchet handle as directly elsewhere on this list.
The multi-language story — Python, Elixir, Rust and PHP workers sharing the same Redis schema — sounds great until you check the PHP port's test suite, which is thin and covers only basic queue operations; don't build production infrastructure on the non-Node ports yet. Like Sidekiq, the genuinely interesting features — job groups, batch processing, group rate limiting — sit behind BullMQ-Pro, priced on request.
And if you outgrow a single Redis node, Cluster mode has real limitations around multi-key Lua scripts — you'll be hand-routing keys, not flipping a config flag.
Our full take →GitHub ↗
★ 13,366GoMITupdated Jun 2026
best for Go teams who want a lean Redis-backed queue without a bigger platform bolted on
Asynq is what you reach for in Go when Celery feels like the wrong language and Hatchet feels like more platform than you need. The ServeMux-style API will feel immediately familiar to anyone who's written a Go HTTP handler, and weighted priority queues and task aggregation are both first-class instead of bolted on.
The honest problem is that it's still pre-1.0, with the maintainers saying directly that APIs can break before it stabilizes — a real risk if you're wiring this into something you don't want to revisit in six months. There's no typed task registry either, so a typo in a task-type string just silently routes nowhere instead of failing loudly, and you're on your own for idempotency since delivery is at-least-once, not exactly-once.
Compare that to River, the other lean Go option here: River trades Redis for Postgres and gets transactional guarantees Asynq simply can't offer, at the cost of needing Postgres instead of whatever you already have running.
Our full take →GitHub ↗
★ 5,361GoMPL-2.0updated Jun 2026
best for teams on Postgres who don't want to run Redis at all
River's whole argument is one sentence: enqueue jobs inside the same Postgres transaction as the work that created them, so a rolled-back transaction means the job never existed. That closes a category of phantom-job bugs that Asynq, BullMQ, and every other Redis-backed queue here can't close, because enqueue and commit are two separate systems for them.
The cost shows up in the packaging: riverdriver, rivershared, rivermigrate, and the SQLite driver are all separate Go modules, so version-pinning across a larger codebase is more fiddly than it should be. SQLite support exists but is clearly second-class — it fakes LISTEN/NOTIFY with a notification outbox, a workaround with different reliability characteristics that isn't well documented. The web UI also lives in its own repo with its own release cadence, so UI and library versions can quietly drift out of sync.
If your job producers need to be polyglot, Python and Ruby can only insert jobs into River — writing an actual worker still means Go, unlike Hatchet, which has full SDK parity across Go, Python, and TypeScript.
Our full take →GitHub ↗
★ 10,650PythonNOASSERTIONupdated Jun 2026
best for small Python projects where Celery's configuration overhead isn't worth it
RQ exists because Celery's configuration surface is a lot to take on for a project that just needs background jobs. Enqueue a function, start a worker, done — no separate DSL, no hundreds of settings to understand before your first job runs. The 2.5 release added a built-in cron scheduler, closing the gap that used to require a separate rq-scheduler sidecar.
The real problem is the default serializer: RQ uses pickle, and deserializing attacker-controlled data with pickle is remote code execution, not a theoretical concern. That warning sits in a box partway down the README instead of JSONSerializer just being the default — switching should be step one, not an afterthought. There's also no result backend beyond a Redis key TTL, so durable job history is on you, and the worker pool doesn't auto-scale — you're back to managing process counts through systemd or Kubernetes at any real load.
It's the right choice specifically when Celery is overkill for your Python project, not a general substitute for it — the two aren't really competing for the same job.
Our full take →GitHub ↗
★ 7,038GoMITupdated Apr 2026
best for teams who want durable retries and a monitoring dashboard built in, not bolted on separately
Hatchet sits a level above everything else on this list — it's not just a queue, it's DAG orchestration, durable execution with sleep/event-wait, per-key concurrency limits, and a dashboard, all running on Postgres the way River does. If you've outgrown what BullMQ or Asynq give you but don't want Temporal's operational weight, this is the gap it's built to fill, and the README is unusually honest about that positioning instead of pretending to replace everything.
Getting there means accepting real self-hosting complexity: Postgres, a message bus, and several internal services, mostly hidden behind a Docker quickstart that doesn't prepare you for production deployment, which is sparsely documented. The quoted ~10k/s throughput ceiling is stated without nuance — no published benchmarks, no breakdown by hardware or task size — so treat it as a rough signal, not a planning number. The Go SDK is also the clunkiest of the three languages offered; the Python and TypeScript SDKs read considerably more naturally.
It ships a full multi-tenant RBAC model whether you need it or not — a solo project or small team self-hosting Hatchet has no easy way to opt into a simpler single-tenant setup.
Our full take →GitHub ↗
// questions people ask
Before you choose
Should I pick based on language or based on infrastructure?
Language first — nobody picks between Celery and Sidekiq, since they only run on Python and Ruby respectively. Once you're inside one language's options, like Asynq versus River versus Hatchet in Go, infrastructure is what actually separates them: what's already running, and what you're willing to add.
Do I need Redis for a background job queue?
No. Sidekiq, BullMQ, and Asynq are all built on Redis and it's not optional for them, but Hangfire uses SQL Server, and River and Hatchet both run on Postgres instead. If you don't already run Redis, River or Hatchet avoid adding it, provided you're on Postgres already.
Which of these have features locked behind a paid tier?
Sidekiq and BullMQ both hold back their more advanced features — cron, batching, and rate limiting for Sidekiq; job groups and batch processing for BullMQ — behind Sidekiq Pro/Enterprise and BullMQ-Pro. Celery, RQ, Hangfire, Asynq, River, and Hatchet ship their core feature sets free; Hangfire's paid tier mostly exists to replace SQL Server polling with push-based scaling.
Is there a safe default if I just want something simple in Python or Go?
In Python, start with RQ unless you already know you need Celery's canvas primitives or multi-broker support — Celery's configuration surface is a lot to take on for a small project. In Go, Asynq is the leanest option; reach for River once you're on Postgres and want transactional job creation, and Hatchet only once you need orchestration, not just a queue.
None of these are wrong, exactly — they're built for different stacks and different tolerances for added infrastructure. If you want repos like this showing up before you go looking for them, that's what the weekly finds.dev email does.