Azure Service Bus Cheat Sheet
Queues, topics, subscriptions, and CLI/SDK patterns for reliable enterprise messaging on Azure Service Bus.
Create Namespace, Queue & Topic (CLI)
Provision a Service Bus namespace with a queue and a topic/subscription.
az servicebus namespace create \ --resource-group rg-messaging \ --name sb-orders-ns \ --sku Standardaz servicebus queue create \ --resource-group rg-messaging \ --namespace-name sb-orders-ns \ --name orders-queue \ --max-delivery-count 10az servicebus topic create \ --resource-group rg-messaging \ --namespace-name sb-orders-ns \ --name orders-topicaz servicebus topic subscription create \ --resource-group rg-messaging \ --namespace-name sb-orders-ns \ --topic-name orders-topic \ --name billing-sub
Send & Receive Messages (Python SDK)
Use azure-servicebus to send a message and process it with peek-lock.
from azure.servicebus import ServiceBusClient, ServiceBusMessageconn_str = "Endpoint=sb://sb-orders-ns.servicebus.windows.net/;..."with ServiceBusClient.from_connection_string(conn_str) as client: with client.get_queue_sender("orders-queue") as sender: sender.send_messages(ServiceBusMessage("order-123", content_type="text/plain")) with client.get_queue_receiver("orders-queue", max_wait_time=5) as receiver: for msg in receiver: print(str(msg)) receiver.complete_message(msg) # removes it from the queue
SQL Filter on a Subscription
Route only high-priority messages to a subscription using a SQL filter rule.
az servicebus topic subscription rule create \ --resource-group rg-messaging \ --namespace-name sb-orders-ns \ --topic-name orders-topic \ --subscription-name billing-sub \ --name HighPriorityOnly \ --filter-sql-expression "priority = 'high'"
Core Concepts
Terminology used across the Service Bus data plane.
- Queue- point-to-point messaging, one consumer processes each message
- Topic/Subscription- pub/sub; each subscription gets a copy matching its filter
- Peek-lock- default receive mode; message is locked, must be completed/abandoned
- Dead-letter queue (DLQ)- holds messages that exceed max delivery count or expire
- Sessions- guarantee FIFO ordering and state for a group of related messages
- Duplicate detection- namespace-level window to drop duplicate MessageIds
Enable Duplicate Detection & Sessions
Configure a session-enabled queue with a duplicate-detection window for exactly-once-ish producer semantics.
az servicebus queue create \ --resource-group rg-messaging \ --namespace-name sb-orders-ns \ --name orders-fifo-queue \ --requires-session true \ --enable-duplicate-detection true \ --duplicate-detection-history-time-window PT10M \ --lock-duration PT1M \ --max-size 5120
Session Processor with Prefetch (.NET)
Process FIFO sessions concurrently while keeping per-session ordering, with prefetch tuned for throughput.
var client = new ServiceBusClient(connectionString);var options = new ServiceBusSessionProcessorOptions{ MaxConcurrentSessions = 20, MaxConcurrentCallsPerSession = 1, PrefetchCount = 50, AutoCompleteMessages = false};await using var processor = client.CreateSessionProcessor("orders-fifo-queue", options);processor.ProcessMessageAsync += async args =>{ var body = args.Message.Body.ToString(); await HandleOrderAsync(args.SessionId, body); await args.CompleteMessageAsync(args.Message);};processor.ProcessErrorAsync += args =>{ Console.WriteLine($"Error in {args.EntityPath}: {args.Exception}"); return Task.CompletedTask;};await processor.StartProcessingAsync();
Drain & Reprocess a Dead-Letter Queue
Read messages from a queue's DLQ sub-queue, inspect the failure reason, and resubmit to the source queue.
from azure.servicebus import ServiceBusClient, ServiceBusMessagewith ServiceBusClient.from_connection_string(conn_str) as client: dlq_receiver = client.get_queue_receiver( "orders-queue", sub_queue="deadletter", max_wait_time=5) sender = client.get_queue_sender("orders-queue") with dlq_receiver, sender: for msg in dlq_receiver: reason = msg.dead_letter_reason desc = msg.dead_letter_error_description print(f"DLQ reason={reason} desc={desc}") if reason == "MaxDeliveryCountExceeded": resubmitted = ServiceBusMessage(str(msg), content_type="text/plain") sender.send_messages(resubmitted) dlq_receiver.complete_message(msg)
Atomic Send + Complete in a Transaction
Use a Service Bus client-side transaction to complete an inbound message and send a follow-up message atomically.
with client.get_queue_receiver("orders-queue") as receiver, \ client.get_queue_sender("billing-queue") as sender: msg = next(iter(receiver.receive_messages(max_message_count=1))) with client.get_service_bus_transaction() as tx: sender.send_messages(ServiceBusMessage("billing-event"), transaction=tx) receiver.complete_message(msg, transaction=tx) # Both operations commit or roll back together
Advanced Feature Reference
Less commonly used but production-critical Service Bus capabilities.
- Auto-forwarding- chain a queue/subscription's output directly into another queue or topic server-side
- Scheduled messages- ScheduledEnqueueTimeUtc delays delivery without a separate scheduler
- Message deferral- DeferMessage sets a message aside by sequence number for out-of-order workflow processing
- Batching (send)- ServiceBusMessageBatch packs multiple messages into one send call to cut overhead
- Geo-disaster recovery- namespace pairing with metadata-only failover; data itself is not replicated
- Premium tier- dedicated messaging units, VNet integration, and predictable low latency vs. Standard's shared capacity
- Partitioned entities- spread a queue/topic across multiple message brokers for higher throughput (Standard tier only)
Enable sessions only when you truly need FIFO per key (e.g. per customer) — session-enabled queues force every receiver to accept a session lock, which hurts throughput if you don't actually need ordering.