Service Bus Topics and Subscriptions
Azure Service Bus Topics and Subscriptions enable a publish-subscribe (pub-sub) messaging pattern. One sender publishes a message to a topic, and multiple independent receivers each get their own copy through subscriptions. This pattern is essential in microservices architectures where a single event must trigger actions in multiple services.
Topic vs Queue — Key Difference
| Feature | Queue | Topic + Subscription |
|---|---|---|
| Receivers | One receiver per message | Multiple receivers per message |
| Pattern | Point-to-Point | Publish-Subscribe |
| Filtering | Not supported | Per-subscription filters |
| Use Case | Task queuing, one processor | Event broadcasting to many services |
How Topics and Subscriptions Work
|--> [Subscription: inventory] --> [Inventory Service]
[Order Service] --> [Topic] |--> [Subscription: email] --> [Email Service]
|--> [Subscription: analytics] --> [Analytics Service]
One message published. Three copies delivered. Each service processes independently.
Real-World Example — Order Event System
A customer places an order. The Order Service publishes one OrderPlaced event to a topic called order-events. Three subscriptions exist:
- inventory-sub: Inventory Service reduces stock
- email-sub: Email Service sends confirmation to the customer
- billing-sub: Billing Service creates an invoice
+----------------------------------------------------------+ | Topic: order-events | | | | [OrderPlaced Message] | | | | | |----> inventory-sub --> [Inventory Service] | | |----> email-sub --> [Email Service] | | '----> billing-sub --> [Billing Service] | +----------------------------------------------------------+
Create a Topic — Azure CLI
az servicebus topic create \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --name order-events \ --default-message-time-to-live P1D \ --max-size 1024
Create Subscriptions on a Topic
# Create inventory subscription az servicebus topic subscription create \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --topic-name order-events \ --name inventory-sub # Create email subscription az servicebus topic subscription create \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --topic-name order-events \ --name email-sub # Create billing subscription az servicebus topic subscription create \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --topic-name order-events \ --name billing-sub
Topic Properties
| Property | Description | Default |
|---|---|---|
| Max Topic Size | Total storage for all subscriptions combined | 1 GB |
| Default Message TTL | How long messages live if not consumed | 14 days |
| Duplicate Detection | Prevents duplicate messages from entering the topic | Disabled |
| Partitioning | Spreads topic data across multiple brokers | Disabled |
| Max Subscriptions | Maximum number of subscriptions allowed per topic | 2000 |
Subscription Properties
| Property | Description | Default |
|---|---|---|
| Lock Duration | How long a consumer holds a message lock | 60 seconds |
| Max Delivery Count | Retry count before moving to Dead Letter Queue | 10 |
| Dead Letter on Expiry | Send expired messages to Dead Letter Queue | Disabled |
| Auto Delete on Idle | Delete the subscription if idle for a set duration | Never |
| Sessions Enabled | Enable session-based ordered delivery | Disabled |
Subscription Filters
Each subscription can have a filter rule that decides which messages it receives from the topic. By default, every subscription receives all messages (True filter). Adding a custom filter lets each subscription see only the messages it cares about.
Filter Types
| Filter Type | Description | Example |
|---|---|---|
| True Filter | All messages pass — default behavior | No rule needed |
| False Filter | No messages pass — subscription receives nothing | Pause a subscription temporarily |
| SQL Filter | SQL WHERE-like expression on message properties | Region = 'India' AND Amount > 100 |
| Correlation Filter | Exact match on one or more built-in or custom properties | Match Label='NewOrder' |
SQL Filter Example
The topic receives order events from all regions. Only the India team subscription should receive orders from India with an amount over 100.
az servicebus topic subscription rule create \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --topic-name order-events \ --subscription-name india-sub \ --name india-filter \ --filter-sql-expression "Region = 'India' AND Amount > 100"
Message 1: { Region: "India", Amount: 500 } --> Passes india-sub filter
Message 2: { Region: "India", Amount: 50 } --> Blocked (Amount not > 100)
Message 3: { Region: "US", Amount: 500 } --> Blocked (Region is not India)
Correlation Filter Example
az servicebus topic subscription rule create \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --topic-name order-events \ --subscription-name email-sub \ --name new-order-filter \ --action-sql-expression "" \ --filter-type CorrelationFilter \ --correlation-filter-label "NewOrder"
Filter Actions — Modifying Messages Before Delivery
A Filter Action modifies message properties after the filter matches. For example, a subscription can stamp an additional property on the message before it reaches the consumer.
Incoming message property: { EventType: "OrderPlaced" }
Action on email-sub: SET Priority = 'High'
Message delivered to email-sub consumer:
{ EventType: "OrderPlaced", Priority: "High" }
Topic and Subscription Diagram — With Filters
Publisher sends: { Region: "India", Amount: 500, Label: "NewOrder" }
|
v
[ Topic: order-events ]
|
|-- [inventory-sub] Filter: True --> ALL messages pass
| --> [Inventory Service] receives message
|
|-- [india-sub] Filter: Region='India' AND Amount > 100
| --> [India Team Service] receives message
|
|-- [email-sub] Filter: Label='NewOrder'
--> [Email Service] receives message
Sending to a Topic (.NET Example)
using Azure.Messaging.ServiceBus;
var client = new ServiceBusClient("<connection-string>");
var sender = client.CreateSender("order-events");
var message = new ServiceBusMessage("{ \"orderId\": 1, \"region\": \"India\", \"amount\": 500 }");
message.ApplicationProperties["Region"] = "India";
message.ApplicationProperties["Amount"] = 500;
message.Subject = "NewOrder";
await sender.SendMessageAsync(message);
Console.WriteLine("Message published to topic.");
Receiving from a Subscription (.NET Example)
var receiver = client.CreateReceiver("order-events", "inventory-sub");
var msg = await receiver.ReceiveMessageAsync();
Console.WriteLine($"Received: {msg.Body}");
await receiver.CompleteMessageAsync(msg);
List Subscriptions on a Topic
az servicebus topic subscription list \ --resource-group rg-messaging-prod \ --namespace-name myshopns \ --topic-name order-events \ --output table
Summary
Topics and Subscriptions implement the publish-subscribe pattern in Azure Service Bus. A sender publishes once to a topic. Each subscription maintains its own independent copy of the message. Filters control which messages each subscription receives, and actions modify message properties before delivery. This design decouples services cleanly and allows each service to evolve independently without affecting others.
