In Microservices Architecture, services need to communicate with each other.
The simplest approach is synchronous HTTP calls, but it creates tight coupling between services.
If one service is slow or unavailable, it affects all dependent services.
Message brokers solve this problem by enabling asynchronous, message-based communication between your services.
Services publish events to the broker, and other services consume them independently.
When you are working in Azure, you can use Azure Service Bus to implement a message broker.
It supports both point-to-point and publish-subscribe messaging patterns.
In this post, we will explore:
- Azure Service Bus: Core Concepts
- How To Create Azure Service Bus in Azure Portal
- Setting Up Azure Service Bus with .NET Aspire
- How to Publish and Consume Messages with Azure Service Bus
- The Event-Driven Pipeline: Payments, Fraud Detection, and Notifications
- Running the Application Locally with Azure Service Bus Emulator
- Deploying Microservices to Azure with Aspire
- Azure Service Bus vs Other Azure Messaging Services
Let's dive in.
👉 Read original article on my newsletter: https://antondevtips.com/blog/building-event-driven-microservices-with-azure-service-bus-in-dotnet
Azure Service Bus: Core Concepts
Azure Service Bus is a fully managed enterprise message broker in the Azure Cloud.
It supports two messaging patterns: Queues and Topics with Subscriptions.
Queues
Queues implement point-to-point communication.
One sender sends a message, and one receiver processes it.
Each message is consumed by exactly one consumer.
Use queues when a message should be processed by a single service.
For example, sending a stock update command to the Stocks service.
Topics with Subscriptions
Topics with Subscriptions implement publish-subscribe communication.
One sender publishes a message to a topic, and multiple subscribers can each receive a copy of that message.
Each subscription acts as its own virtual queue.
Use topics when multiple services need to react to the same event.
For example, when a payment is processed, both the Fraud Detection service and the Notifications service may need to be notified.
Our solution has five microservices that communicate through Azure Service Bus:
- Product-Service - manages products and handles purchases
- Stock-Service - manages product stock levels
- Payment-Service - processes payments and tracks their status
- FraudDetection-Service - analyzes payments for fraud risk
- Notification-Service - sends email notifications
Here is the message flow:
When a user purchases a product:
-
Product-Service publishes
UpdateStockEventto theupdate-stockqueue andPurchaseCompletedEventto thepayment-createdqueue -
Stock-Service consumes from
update-stockand updates the stock count -
Payment-Service consumes from
payment-created, creates a payment record, and publishesPaymentRegisteredEventto thepayment-registeredtopic -
FraudDetection-Service subscribes to the
payment-registeredtopic, analyzes the payment, and publishesFraudDecisionEventto thefraud-decisionqueue -
Payment-Service consumes from
fraud-decision, updates the payment status, and publishesPaymentProcessedEventto thepayment-processedtopic -
Notification-Service subscribes to the
payment-processedtopic and sends a notification
In our project, we use both:
-
Queues for
update-stock,payment-created, andfraud-decision(one sender, one receiver) -
Topics for
payment-registeredandpayment-processed(one sender, multiple receivers)
How Messages Flow Through Service Bus
When a consumer receives a message, Service Bus does not delete it immediately.
It locks the message and hides it from other consumers for a configurable lock duration.
The consumer has that time to process the message and complete the call.
If it completes successfully, Service Bus deletes the message.
If the handler throws or the lock expires, Service Bus releases the message and makes it available for retry.
Service Bus tracks how many times a message has been delivered using the delivery count.
When the delivery count exceeds MaxDeliveryCount (default: 10), Service Bus automatically moves the message to the dead-letter queue.
At-least-once delivery is the core guarantee Service Bus provides.
A message will be delivered at least once, but in rare cases it may be delivered more than once — for example, if a network failure prevents the completion acknowledgement from reaching the Service Bus.
Your consumers must be idempotent: processing the same message twice must produce the same result.
Dead-Letter Queue
Every queue and every topic subscription has a built-in dead-letter sub-queue (DLQ).
Messages end up in the DLQ when:
- The delivery count exceeds
MaxDeliveryCount - Your code explicitly calls
DeadLetterMessageAsync— for example, when a message is malformed, and retrying is pointless - The message TTL (time-to-live) expires before it is consumed
The DLQ is permanent — messages do not expire there.
You can inspect, replay, or archive them using the Azure Portal.
In production, monitor the DLQ message count and set up alerts.
A growing DLQ means something in your pipeline is consistently failing.
Duplicate Detection
Service Bus can automatically discard duplicate messages within a configurable time window.
Enable it on a queue or topic at creation time.
Service Bus tracks messages by their MessageId.
If a message with the same MessageId arrives within the duplicate detection window (default: 10 minutes), Service Bus silently drops it.
Use duplicate detection when your producer may retry sending — for example, after a timeout or a transient network failure.
Message Sessions
Sessions enable ordered, grouped processing of related messages.
Set a SessionId on each message to group them together.
Service Bus guarantees that all messages with the same SessionId are processed in order by a single consumer at a time.
No two consumers can process messages from the same session simultaneously.
Use sessions when order matters — for example, processing all state transitions for the same payment in sequence.
Sessions require RequiresSession = true on the queue or subscription.
How To Create Azure Service Bus in Azure Portal
First, create a new Azure Service Bus namespace in the Azure Portal.
Go to the Azure Portal and search for "Service Bus":
Create a new Service Bus namespace with the following settings:
- Resource group: Choose your resource group or create a new one
- Namespace name: Choose a globally unique name
- Location: Select the region closest to your services
- Pricing tier: Select Standard
The pricing tier is important.
The Basic tier only supports queues.
If you need topics and subscriptions (which we do), you must use at least the Standard tier.
For most development and production workloads, Standard is sufficient.
Choose Premium only if you need dedicated resources, virtual network integration, or messages larger than 256 KB.
👉 Read original article on my newsletter: https://antondevtips.com/blog/building-event-driven-microservices-with-azure-service-bus-in-dotnet
Top comments (0)