← Back to Topics

Topic

Background Jobs & Async

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

Why Your Sidekiq Job Runs Twice (At-Least-Once Delivery Explained)

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.

·14 min read

More articles