← All topics
📬 Messaging & NServiceBus

Retry & Dead Letter Queue

What happens when a handler throws.

Immediate retries — when a handler throws, the message broker/framework retries processing right away, a few times, for transient failures (a brief DB blip, a momentary network error) that are likely to succeed on the very next attempt.

Delayed/exponential-backoff retries — if immediate retries are exhausted, wait progressively longer between further attempts (e.g. 10s, then 1min, then 10min) — for failures that need more time to resolve (a downstream service restarting, a rate limit cooling down) rather than hammering it instantly N more times.

Dead Letter Queue (DLQ) — after all retry policies are exhausted, the message is moved to a separate queue instead of being silently dropped or retried forever. This is critical: it preserves the message for inspection/manual intervention/replay, and — just as importantly — stops one poison message from blocking the whole queue behind it forever. NServiceBus calls this its error queue; the underlying idea is identical to RabbitMQ/Azure Service Bus DLQs.

What you should actually say if asked "how would you handle a message that keeps failing": separate transient failures (network blip — retry) from permanent ones (malformed message, business rule that will never pass — no amount of retrying fixes a poison message), and make sure the poison message ends up in a DLQ with enough context (the original message + the exception) to diagnose it later, rather than being retried forever or silently swallowed.

Flashcards (3)

What's the difference between immediate retries and delayed/exponential-backoff retries, and when is each appropriate?
tap to reveal answer
Immediate retries happen right away, a few times — good for very brief transient blips likely to resolve instantly. Delayed/backoff retries wait progressively longer between attempts — good for failures needing more time to resolve (a dependent service restarting, a rate limit), avoiding hammering it repeatedly.
What is a Dead Letter Queue and what TWO problems does it solve?
tap to reveal answer
A separate queue messages move to once all retries are exhausted. It (1) preserves the failed message for inspection/manual fix/replay instead of losing it, and (2) prevents one permanently-failing ('poison') message from blocking every message behind it in the main queue.
If asked 'how would you handle a message that keeps failing', what's the key distinction to draw in your answer?
tap to reveal answer
Transient failures (network blip, momentary DB unavailability) are worth retrying since they're likely to resolve. Permanent/'poison' failures (malformed message, a business rule that will never pass) will never succeed no matter how many retries — they should go straight to (or quickly reach) a DLQ with enough context to diagnose, not be retried forever.