tanjilahmed87@gmail.com

Backend6 min read

RabbitMQ Patterns for Reliable Background Processing

RabbitMQ's flexibility means there are several ways to build a queue, and only some of them survive a worker crashing mid-message.

Tanjil Ahmed

Lead Software Engineer · Notionhive

RabbitMQ gives you enough low-level control to build a queue several different ways, and the difference between those ways shows up exactly once — the first time a worker crashes mid-message, and either the message is safely redelivered or it's gone forever.

  • Manual acknowledgment, not auto-ack — a worker crash before ack means RabbitMQ redelivers the message instead of silently dropping it.
  • Dead-letter exchanges for messages that fail repeatedly, so a poison message doesn't loop forever or block the queue.
  • Idempotent consumers, always — 'at least once' delivery is the realistic guarantee, and duplicate processing will eventually happen.
  • Prefetch count tuned to worker capacity — an unbounded prefetch lets one slow worker hoard messages other idle workers could process.

The incidents I've debugged in queue-based systems were never about RabbitMQ being unreliable — they were about a consumer written assuming exactly-once delivery, which message queues don't actually offer without deliberate idempotency on the consumer's side.

RabbitMQ promises at-least-once delivery. If your consumer isn't idempotent, that promise becomes your bug.