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

FeatureQueueTopic + Subscription
ReceiversOne receiver per messageMultiple receivers per message
PatternPoint-to-PointPublish-Subscribe
FilteringNot supportedPer-subscription filters
Use CaseTask queuing, one processorEvent 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

PropertyDescriptionDefault
Max Topic SizeTotal storage for all subscriptions combined1 GB
Default Message TTLHow long messages live if not consumed14 days
Duplicate DetectionPrevents duplicate messages from entering the topicDisabled
PartitioningSpreads topic data across multiple brokersDisabled
Max SubscriptionsMaximum number of subscriptions allowed per topic2000

Subscription Properties

PropertyDescriptionDefault
Lock DurationHow long a consumer holds a message lock60 seconds
Max Delivery CountRetry count before moving to Dead Letter Queue10
Dead Letter on ExpirySend expired messages to Dead Letter QueueDisabled
Auto Delete on IdleDelete the subscription if idle for a set durationNever
Sessions EnabledEnable session-based ordered deliveryDisabled

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 TypeDescriptionExample
True FilterAll messages pass — default behaviorNo rule needed
False FilterNo messages pass — subscription receives nothingPause a subscription temporarily
SQL FilterSQL WHERE-like expression on message propertiesRegion = 'India' AND Amount > 100
Correlation FilterExact match on one or more built-in or custom propertiesMatch 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.

Leave a Comment