← Back to Tutorials
Beginner⏱️ 25 min

Topics, Subscriptions, and Message Filtering

Topics, Subscriptions, and Message Filtering

Topics vs Queues

FeatureQueueTopic
PatternPoint-to-pointPublish/Subscribe
ConsumersSingle consumer per messageMultiple subscriptions receive copies
Use CaseTask distributionEvent broadcasting
FilteringN/ASQL and Correlation filters

Architecture — Pub/Sub with Topics

                              ┌─────────────────────┐
                              │  Subscription:       │
                         ┌───▶│  inventory-sub       │───▶ Inventory Service
                         │    │  Filter: eventType=  │
                         │    │  'OrderCreated'      │
                         │    └─────────────────────┘
┌──────────┐    ┌────────┴──────────┐
│ Producer │───▶│   order-events    │    ┌─────────────────────┐
│  (App)   │    │     (Topic)       │───▶│  Subscription:       │
└──────────┘    └────────┬──────────┘    │  billing-sub         │
                         │               │  Filter: amount>100  │
                         │               └─────────────────────┘
                         │    ┌─────────────────────┐
                         └───▶│  Subscription:       │
                              │  notifications-sub   │
                              │  Filter: (all)       │
                              └─────────────────────┘

Prerequisites

RequirementDetails
Service Bus NamespaceStandard or Premium tier
Azure CLIv2.50+
.NET SDK8.0+

Step 1 — Create a Topic

az servicebus topic create \
  --name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo \
  --default-message-time-to-live P7D

Screenshot: Topic created in portal

Step 2 — Create Subscriptions

# Subscription for inventory service
az servicebus topic subscription create \
  --name inventory-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo

# Subscription for billing service
az servicebus topic subscription create \
  --name billing-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo

# Subscription for notifications
az servicebus topic subscription create \
  --name notifications-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo

Screenshot: Subscriptions listed in portal

Step 3 — Add SQL Filters

SQL filters evaluate a SQL-like expression against message application properties.

# Remove the default "match all" rule from billing-sub
az servicebus topic subscription rule delete \
  --name '$Default' \
  --subscription-name billing-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo

# Add SQL filter: only messages where amount > 100
az servicebus topic subscription rule create \
  --name high-value-orders \
  --subscription-name billing-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo \
  --filter-sql-expression "amount > 100"

Step 4 — Add Correlation Filters

Correlation filters match against message properties efficiently (hash-based lookup).

# Remove default rule from inventory-sub
az servicebus topic subscription rule delete \
  --name '$Default' \
  --subscription-name inventory-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo

# Add correlation filter
az servicebus topic subscription rule create \
  --name order-created-filter \
  --subscription-name inventory-sub \
  --topic-name order-events \
  --namespace-name sb-demo-namespace \
  --resource-group rg-servicebus-demo \
  --correlation-filter application-properties="eventType=OrderCreated"
Filter TypePerformanceUse Case
SQL FilterSlower (expression evaluation)Complex conditions, ranges, LIKE
Correlation FilterFaster (hash match)Exact property matching
True Filter (default)N/AReceive all messages

Step 5 — Send Messages to a Topic

using Azure.Messaging.ServiceBus;

const string connectionString = "<YOUR_CONNECTION_STRING>";
const string topicName = "order-events";

await using var client = new ServiceBusClient(connectionString);
ServiceBusSender sender = client.CreateSender(topicName);

// High-value order (reaches billing-sub and notifications-sub)
var highValueOrder = new ServiceBusMessage("High value order: $250")
{
    ApplicationProperties =
    {
        { "eventType", "OrderCreated" },
        { "amount", 250 }
    }
};
await sender.SendMessageAsync(highValueOrder);

// Low-value order (only reaches notifications-sub)
var lowValueOrder = new ServiceBusMessage("Low value order: $25")
{
    ApplicationProperties =
    {
        { "eventType", "OrderCreated" },
        { "amount", 25 }
    }
};
await sender.SendMessageAsync(lowValueOrder);

Console.WriteLine("Messages sent to topic.");

Step 6 — Receive from a Subscription

using Azure.Messaging.ServiceBus;

const string connectionString = "<YOUR_CONNECTION_STRING>";
const string topicName = "order-events";
const string subscriptionName = "billing-sub";

await using var client = new ServiceBusClient(connectionString);
ServiceBusReceiver receiver = client.CreateReceiver(topicName, subscriptionName);

IReadOnlyList<ServiceBusReceivedMessage> messages =
    await receiver.ReceiveMessagesAsync(maxMessages: 10, maxWaitTime: TimeSpan.FromSeconds(5));

foreach (var msg in messages)
{
    Console.WriteLine($"Billing received: {msg.Body} | Amount: {msg.ApplicationProperties["amount"]}");
    await receiver.CompleteMessageAsync(msg);
}

Screenshot: Subscription receiving filtered messages

Real-World Scenario — Order Events

When an order is placed, multiple services need to react independently:

  • Inventory Service — reserves stock (filter: eventType = 'OrderCreated')
  • Billing Service — charges card for high-value orders (filter: amount > 100)
  • Notification Service — sends confirmation email (no filter, receives all)

Each subscription processes messages at its own pace without blocking others.

Summary

  • ✅ Understood Topics vs Queues (pub/sub pattern)
  • ✅ Created a topic with multiple subscriptions
  • ✅ Applied SQL and Correlation filters
  • ✅ Sent messages with application properties
  • ✅ Received filtered messages from subscriptions

Previous: Send and Receive Messages with .NET SDK

Next: Dead Letter Queues — Handling Failed Messages