In modern cloud-based systems, decoupling different components or services improves scalability, resilience, and maintainability. Azure Service Bus is one of the most popular managed messaging services for achieving this in Microsoft Azure.
In this blog, you’ll learn:
How Service Bus helps decouple applications
The sender-receiver model
How to implement it using .NET with practical code
🔗 What is Azure Service Bus?
Azure Service Bus is a fully managed enterprise message broker that allows different parts of your application to communicate asynchronously via messages.
Sender: Sends a message to a queue (one-to-one) or topic (one-to-many).
Receiver: Reads messages from the queue or subscription.
🧩 Typical Use Case
Imagine a web application where users upload images for processing:
The web API sends a message to the Service Bus queue describing the image.
A background worker receives and processes the image asynchronously.
The API remains responsive while processing happens in the background.
🛠️ Setting Up
Before coding:
Create an Azure Service Bus namespace.
Create a queue (e.g.,
image-queue
).Get the connection string from the Azure portal.
💻 .NET Code: Sending a Message
Here’s how to create a sender in a console app:
using Azure.Messaging.ServiceBus;
string connectionString = "<your_service_bus_connection_string>";
string queueName = "image-queue";
// Create a ServiceBusClient
await using var client = new ServiceBusClient(connectionString);
// Create a sender for the queue
ServiceBusSender sender = client.CreateSender(queueName);
try
{
string messageBody = "Image uploaded: /images/img123.jpg";
ServiceBusMessage message = new ServiceBusMessage(messageBody);
await sender.SendMessageAsync(message);
Console.WriteLine($"Sent: {messageBody}");
}
finally
{
await sender.DisposeAsync();
}
Explanation:
We create a
ServiceBusClient
using the connection string.We get a
ServiceBusSender
for our queue.We create and send a simple text message.
Finally, we dispose of the sender to clean up resources.
Pro Tip: Batching
If you’re sending many messages, you can use sender.SendMessagesAsync(IEnumerable<ServiceBusMessage>)
for better throughput.
Uncover more by visiting :
https://dotnetfullstackdev.medium.com/
📥 .NET Code: Receiving Messages
Here’s how to create a receiver:
using Azure.Messaging.ServiceBus;
string connectionString = "<your_service_bus_connection_string>";
string queueName = "image-queue";
// Create a ServiceBusClient
await using var client = new ServiceBusClient(connectionString);
// Create a processor that listens for messages
ServiceBusProcessor processor = client.CreateProcessor(queueName, new ServiceBusProcessorOptions());
// Define the message handler
processor.ProcessMessageAsync += async args =>
{
string body = args.Message.Body.ToString();
Console.WriteLine($"Received: {body}");
// Simulate processing (e.g., image resize)
await Task.Delay(500);
Console.WriteLine("Processing completed.");
// Complete the message so it is not received again
await args.CompleteMessageAsync(args.Message);
};
// Define the error handler
processor.ProcessErrorAsync += args =>
{
Console.WriteLine($"Error: {args.Exception.Message}");
return Task.CompletedTask;
};
// Start processing
await processor.StartProcessingAsync();
Console.WriteLine("Listening for messages... Press any key to stop.");
Console.ReadKey();
// Stop processing
await processor.StopProcessingAsync();
Explanation:
We create a
ServiceBusProcessor
with default options.We register handlers:
ProcessMessageAsync: handles incoming messages.
ProcessErrorAsync: logs errors during processing.
We call
StartProcessingAsync
to start listening.CompleteMessageAsync
ensures the message is marked as processed.
🔄 Communication Flow
Sender app sends a message to the queue.
Service Bus stores the message until a receiver processes it.
Receiver app picks up the message, processes it, and marks it as complete.
This decouples the sender from the receiver. If the receiver is offline, the message is stored durably until it can be processed — ensuring reliability.
🛡️ Best Practices
Use async/await to avoid blocking.
Use error handling to catch transient failures and implement retries if needed.
Dead-letter messages if they fail repeatedly.
Use Azure Managed Identity instead of connection strings for better security (when deployed in Azure).
✅ Conclusion
With Azure Service Bus, senders and receivers operate independently, ensuring your app is resilient and scalable.
Sender: creates a message and sends it to the queue.
Receiver: listens, processes, and completes the message.
Using .NET, it’s straightforward to implement both ends, and this approach is a foundational piece of modern cloud architectures