Skip to content

Retry Policies

Retry policies define how a subscriber can reprocess messages that fail during handling.

ServiceBus.Core.Rabbit implements subscriber retry by creating a RabbitMQ retry topology based on:

  • a DLX exchange;
  • a retry exchange;
  • a retry queue;
  • message TTL;
  • dead-letter routing back to the main queue.

Retry Condition

A message enters the retry flow only when the message handler completes with:

args.Acknowledged = false;
args.Requeue = true;

If Acknowledged is true, the message is completed.

If Requeue is false, the message is not sent through the retry flow.


Retry Topology

When retry is enabled, the provider builds an auxiliary topology around the main queue.

graph LR
    MainQueue["Main Queue"]
    Subscriber["Subscriber"]
    DlxExchange["DLX Exchange<br/>queue_dlx"]
    RetryQueue["Retry Queue<br/>queue_retry"]
    RetryExchange["Retry Exchange<br/>queue_retry"]

    MainQueue --> Subscriber
    Subscriber -->|"Acknowledged = false<br/>Requeue = true"| DlxExchange
    DlxExchange --> RetryQueue
    RetryQueue -->|"x-message-ttl expires"| RetryExchange
    RetryExchange --> MainQueue

Generated Objects

The retry topology is created from the main queue.

If the queue logical name is:

orders.created

the retry infrastructure is derived using suffixes:

Object Suffix
DLX exchange _dlx
Retry exchange _retry
Retry queue _retry

Retry Queue Arguments

The retry queue is created with RabbitMQ arguments similar to:

Arguments =
{
    ["x-message-ttl"] = retryPolicy.Delayed.TotalMilliseconds,
    ["x-dead-letter-exchange"] = retryExchange.FullName,
    ["x-queue-type"] = queueType
};

Where x-queue-type is copied from the main queue when available.

If the main queue does not define a queue type, the retry queue uses:

classic

Binding Flow

The provider creates the following bindings:

DLX Exchange -> Retry Queue

Retry Exchange -> Main Queue

This creates a delayed retry loop:

Main Queue
  -> Subscriber failure
  -> DLX Exchange
  -> Retry Queue
  -> TTL expires
  -> Retry Exchange
  -> Main Queue

When Retry Is Useful

Retries are useful for transient failures, such as:

  • temporary database unavailability;
  • network interruptions;
  • downstream service timeouts;
  • temporary lock conflicts.

When Retry Is Not Useful

Retries are usually not useful for:

  • invalid payloads;
  • unsupported message versions;
  • business validation failures;
  • missing required data.

For these cases, set:

args.Acknowledged = false;
args.Requeue = false;

so the message is not sent back through the retry loop.