Solid Queue vs Sidekiq: How to Actually Decide (Rails 8)
Solid Queue vs Sidekiq isn't a throughput threshold — it's about where your complexity lives and whether your database can absorb the queue. A decision framework.
Topic
Moving slow or unreliable work off the request path is one of the highest-leverage decisions in a backend — and the moment that work runs in a queue, the reliability contract quietly changes. A background job does not run exactly once. It runs at least once: a deploy, a timeout, a retry, or a lost acknowledgement can re-run a job you thought had finished. That is not a flaw to configure away; it is the guarantee you are building on.
So the hard part was never enqueuing the work — it is what happens on the second run. Retries repeat side effects that already happened; two duplicate deliveries race the same record in parallel; a worker crashes mid-flight and strands the job. None of that is fixable at the queue layer, because the queue only knows about delivery, not about the charge, the email, or the row you actually care about. Correctness has to move down to the one component that can adjudicate a race under concurrency: the database.
This hub collects the deep dives on that idea — at-least-once delivery and why jobs run twice, idempotent workers keyed on stable identifiers, atomic claims and unique constraints that make duplicates impossible to persist, fencing tokens, reapers, and the failure modes that only ever show up in production. The thread running through all of it: the queue provides delivery; the database enforces correctness.
Start here
Sidekiq runs jobs at least once, not exactly once. Here's why background jobs execute twice — deploys, retries, timeouts, lost acks — and where the fix actually lives.
More articles
Solid Queue vs Sidekiq isn't a throughput threshold — it's about where your complexity lives and whether your database can absorb the queue. A decision framework.
A “slow” background job either waited (queue latency) or ran slowly (execution time). Measure which — then a diagnostic method for fixing each, in Rails.
A deep look at Solid Queue internals — execution tables, SKIP LOCKED claiming, concurrency controls, heartbeats — and the one guarantee it doesn't give you.
Not every failed job should retry. A practical guide to Sidekiq retry strategy — backoff, error classification, the Dead Set, and when to stop.
An LLM call behind a Sidekiq job runs at least once, not exactly once. How to make Rails workers idempotent so a retry never double-classifies or double-bills.