Dead-Letter Strategies¶
This guide explains how dead-letter handling works in the ServiceBus RabbitMQ implementation.
It is important to distinguish between:
- the automatic retry topology managed by the library;
- custom dead-letter queues implemented directly in RabbitMQ.
These are different mechanisms intended for different scenarios.
Automatic Retry Topology¶
The ServiceBus library provides a built-in retry mechanism through the RetryPolicy property of SubscriberBoundDescriptor.
var descriptor = new SubscriberBoundDescriptor
{
RetryPolicy = new RetryPolicyDescriptor
{
Enabled = true,
MaxRetry = 5,
Delayed = TimeSpan.FromSeconds(30)
}
};
When retries are enabled, the retry topology is generated automatically during subscriber initialization.
The topology is derived from:
SubscriberBoundDescriptor.QueueSubscriberBoundDescriptor.RetryPolicy
No additional RabbitMQ objects need to be configured.
Automatically Created Topology¶
When the subscriber starts, the library automatically creates the required RabbitMQ resources.
The generated topology consists of:
- a Dead-Letter Exchange (
<queue>_dlx); - a Retry Exchange (
<queue>_retry); - a Retry Queue (
<queue>_retry).
The retry queue is configured internally with:
x-message-ttlx-dead-letter-exchangex-queue-type
The required bindings between these resources are also created automatically.
flowchart LR
MainQueue["orders"]
DLX["orders_dlx"]
RetryQueue["orders_retry"]
RetryExchange["orders_retry"]
MainQueue -->|Rejected| DLX
DLX --> RetryQueue
RetryQueue -->|TTL expired| RetryExchange
RetryExchange --> MainQueue
The retry topology is completely managed by the library.
Retry Configuration¶
Applications configure retries exclusively through RetryPolicyDescriptor.
Example:
RetryPolicy = new RetryPolicyDescriptor
{
Enabled = true,
MaxRetry = 5,
Delayed = TimeSpan.FromSeconds(30),
Durable = true,
AutoDelete = false
}
The library uses this configuration to create the retry queue and exchanges.
Applications do not create or configure these RabbitMQ resources directly.
Manual Configuration¶
The retry topology is not intended to be configured manually.
The library owns the lifecycle of:
- the retry queue;
- the retry exchange;
- the dead-letter exchange;
- the required bindings.
Applications should only configure the RetryPolicy.
Changing or creating these resources manually may produce an inconsistent topology and is therefore not supported.
Custom Dead-Letter Queues¶
Some systems require permanent dead-letter queues for operational analysis or manual message recovery.
This scenario is different from the automatic retry mechanism provided by the library.
A custom Dead-Letter Queue (DLQ) is implemented directly in RabbitMQ using queue arguments such as:
x-dead-letter-exchangex-dead-letter-routing-key
These queues are entirely managed by the application or the RabbitMQ administrator and are outside the scope of the library retry mechanism.
Retry vs Dead-Letter Queue¶
| Automatic Retry | Custom Dead-Letter Queue |
|---|---|
| Managed by the library | Managed by the application |
Configured through RetryPolicyDescriptor |
Configured directly in RabbitMQ |
| Retry queue and exchanges created automatically | RabbitMQ resources created manually |
| Used for delayed retry processing | Used for permanent message isolation |
| No manual RabbitMQ configuration required | Full RabbitMQ configuration required |
Best Practices¶
- Configure retries only through
SubscriberBoundDescriptor.RetryPolicy. - Do not manually create or modify the retry queue or retry exchanges.
- Let the library manage the retry topology.
- Use custom Dead-Letter Queues only when messages must be permanently isolated after processing failures.