How to Design Background Jobs That Do Not Lose Work

A background job is reliable when the product can tolerate it running late, more than once, or after a process crash—without silently losing the intended work. “We call a queue after saving” is not that guarantee.

Make the handoff durable

When a request changes durable state and requires follow-up work, store both the state change and a pending event in the same database transaction. A separate worker reads that outbox, delivers the job, and records delivery attempts.

flowchart LR
  accTitle: Durable background work handoff
  accDescr: An API transaction stores product state and an outbox event. A worker delivers the event to a queue and a job consumer performs idempotent work with monitoring and replay support.
  A["API transaction"] --> D[("Product state")]
  A --> O[("Outbox event")]
  O --> W["Delivery worker"]
  W --> Q["Queue"]
  Q --> C["Idempotent consumer"]
  C --> M["Logs, metrics, alerts"]

Without this pattern, a server can commit the request and crash before it publishes the message. The user sees success; the downstream work never happens.

Assume at-least-once delivery

Most practical queues may deliver more than once. Make consumers idempotent using a durable operation key, a unique constraint, or an explicit processed-event record. Do not try to promise “exactly once” by assuming a network call cannot time out after the remote system accepted it.

Retrying needs a policy

Classify errors. Retry temporary provider failures with exponential backoff and a bounded attempt count. Do not retry invalid input forever. Send exhausted jobs to a visible failure state, alert an owner, and provide a safe replay path after the root cause is fixed.

Observe the work, not just the queue

Track pending outbox age, job latency, success rate, retry count, and dead-letter count. Include a correlation ID from the initiating request in each log and downstream call. The operational question should be answerable: “Did this customer action finish, and if not, where is it stuck?”

Reliable job design is a core part of production readiness, not infrastructure polish for later.

01 / Newsletter

Practical notes for building work that lasts.

Occasional field notes on product engineering, architecture, and delivery. No recycled growth hacks.

Stay in the loop

Check your inbox to confirm your subscription.

Your email will be processed by Brevo. Unsubscribe anytime.