In the post below, we discussed how Azure Service Bus integrates with a .NET application and the benefits it provides.
https://dev.to/kiranrongali/why-use-azure-service-bus-how-to-integrate-in-net-13f9

But what happens if a failure occurs during message processing? How does retry behavior work, and how many times will it attempt to process the message again? This post will help you understand that process.

When your message processor (receiver) throws an exception or fails to call CompleteMessageAsync, Azure Service Bus automatically retries processing that message, based on its configured max delivery count.

Retry Behavior (Default)
If your handler fails or throws an exception → message is re-delivered

This retry continues until:
The message is successfully completed (CompleteMessageAsync)
The max delivery count is exceeded

What Happens After Max Retries?
Once the message exceeds the MaxDeliveryCount (default: 10), it is moved to the Dead-Letter Queue (DLQ).

Dead-Letter Queue
This is a special sub-queue where failed messages are stored for inspection, manual or automated reprocessing.

You can access the DLQ like this:

#csharp
var receiver = client.CreateReceiver("your-queue-name", new ServiceBusReceiverOptions
{
    SubQueue = SubQueue.DeadLetter
});

What You Need to Do

  • Proper Error Handling Wrap your message processing in try/catch:
#csharp
processor.ProcessMessageAsync += async args =>
{
    try
    {
        var body = args.Message.Body.ToString();
        Console.WriteLine($"Processing: {body}");

        // Your logic here

        await args.CompleteMessageAsync(args.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex.Message}");
        // Do NOT complete the message → it will retry
        // Optionally log or notify
    }
};
  • Configure MaxDeliveryCount In Azure Portal → Service Bus Queue → Properties, you can set MaxDeliveryCount.

Or via ARM/CLI:

#json
"maxDeliveryCount": 5
  • Monitor the Dead-Letter Queue

Use: Azure Portal (Explore Dead-letter queue)

Azure Monitor / Alerts

Code-based reprocessing via SubQueue.DeadLetter

Optional: Auto Retry with Delay
Azure Service Bus doesn’t support native delayed retries (e.g., exponential backoff), but you can:

Use Scheduled Enqueue Time to requeue a message after a delay

Move failed messages to a custom retry queue with delay

Example of scheduling a retry:

#csharp
var retryMessage = new ServiceBusMessage("retry this")
{
    ScheduledEnqueueTime = DateTimeOffset.UtcNow.AddMinutes(5)
};
await sender.SendMessageAsync(retryMessage);

Best Practices:

  • Use try/catch to Prevent app crashes & enable retry logic
  • Use Monitor DLQ to Avoid silent message losses
  • Use custom retry queues for control over backoff and limits
  • Handle poison messages Log, alert, or notify for manual review

That's it for this Part1 and Part 2 will be covered in a separate post, focusing on the retry flow and monitoring the Dead-Letter Queue (DLQ).