Dead-letter queue — the escape valve
When a message's delivery count crosses maxReceiveCount, the broker moves it to a sibling DLQ — freeing the main pool and giving ops a quarantine to inspect and redrive once the underlying bug is fixed.
The badge climbing past a threshold is the broker's only signal that this message is poison rather than transient. So we route it to a sibling channel — quarantine — and let ops decide when (and whether) to redrive it.
Scene 08
Dead-letter queue — the escape valve
- Watch
- Try it
- Predict
- Capture
Same poison cell from the last scene — but now the broker watches the badge. Workers grab it, fail, the count ticks 1, 2, 3. At maxReceiveCount=3 the cell slides down the chute into the DLQ. The main queue keeps going; the workers can finally drain the healthy cells behind it.
Highlighted lines are the ones running in the diagram right now.
def nack(cell, requeue=True):cell.deliveryCount += 1if cell.deliveryCount >= maxReceiveCount:# quarantine: sibling queue, no workers attacheddlq.append(cell)returnif requeue:# back to the head, next worker grabs itmainQueue.pushFront(cell)# else: drop silently (rare; opt-in)
def redrive():# ops triggers this AFTER fixing the underlying bugwhile not dlq.empty():cell = dlq.popFront()cell.deliveryCount = 0 # fresh attempts budgetmainQueue.pushBack(cell)# DLQ does NOT drain on its own — quarantine is sticky
# threshold = 1: trigger-happy# one nack -> DLQ, no retry budget at allconfig.maxReceiveCount = 1# a 200ms DB blip at 1000 msg/s -># ~200 healthy messages quarantined per blip# threshold = 100: slow quarantine# poison cell loops 99 extra timesconfig.maxReceiveCount = 100# workers pinned; healthy traffic starves# sweet spot in practice: 3..10
Where this sits in Build a Message Queue (RabbitMQ / SQS)
Scene 08 of 14. After N redeliveries, the broker routes the cell to a sibling DLQ; the main pool keeps moving. maxReceiveCount is the knob with two failure modes.
Up next. Delivery count rises only when the consumer actually nacks. But what if the consumer just goes silent — long GC pause, OOM, hung syscall? The broker can't wait forever. It needs a second clock.
All 14 scenes in Build a Message Queue (RabbitMQ / SQS) · Every curriculum