Azure Service Bus and Event Hubs are both messaging services in Azure, but they solve fundamentally different problems, and picking the wrong one can lead to performance headaches and unexpected costs.
Imagine you’re building a system where one part needs to tell another part to do something, and that "something" needs to be reliably processed exactly once. That’s Service Bus. Think of it like a postal service: you send a letter (a message), and the recipient gets it, reads it, and can confirm they’ve dealt with it. This is crucial for tasks like processing orders, sending notifications, or updating a database record where duplicates or lost messages are a disaster.
Here’s Service Bus in action, sending a message to a queue named my-order-queue:
# Install Azure Messaging module if you haven't already
# Install-Module -Name Az.ServiceBus -Scope CurrentUser
$serviceBusNamespace = "your-servicebus-namespace.servicebus.windows.net"
$queueName = "my-order-queue"
$connectionString = "Endpoint=sb://{your-servicebus-namespace}.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SHARED_ACCESS_KEY"
# Create a Service Bus client
$client = New-AzServiceBus -Namespace $serviceBusNamespace -Queue $queueName -ConnectionString $connectionString
# Send a message
$message = New-AzServiceBusMessage -Body "New order received: OrderID 12345"
$client.Send($message)
Write-Host "Message sent to queue: $queueName"
And here’s how a receiver would pick it up, ensuring it’s processed exactly once:
# Install Azure Messaging module if you haven't already
# Install-Module -Name Az.ServiceBus -Scope CurrentUser
$serviceBusNamespace = "your-servicebus-namespace.servicebus.windows.net"
$queueName = "my-order-queue"
$connectionString = "Endpoint=sb://{your-servicebus-namespace}.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SHARED_ACCESS_KEY"
# Create a Service Bus client
$client = New-AzServiceBus -Namespace $serviceBusNamespace -Queue $queueName -ConnectionString $connectionString
# Receive and complete a message
# PeekLock mode is default and ensures the message is locked for processing
$message = $client.Receive()
if ($message) {
Write-Host "Received message: $($message.Body)"
# Process the message here...
$client.Complete($message.LockToken) # Acknowledge successful processing
Write-Host "Message completed."
} else {
Write-Host "No messages in the queue."
}
The mental model for Service Bus is a reliable, ordered delivery system for individual work items. It offers features like:
- Queues: For point-to-point communication. One sender, one receiver (or competing receivers).
- Topics/Subscriptions: For publish-subscribe patterns. One sender, multiple receivers, each getting a copy of the message.
- Transactions: Grouping multiple send/receive operations into an atomic unit.
- Dead-lettering: Automatically moving messages that can’t be processed after a certain number of retries to a special queue for inspection.
- Scheduled delivery: Sending a message that will only become available at a future time.
- Message deferral: A receiver can choose to defer processing a message for later, without losing it.
Service Bus is built for scenarios where the state of a message is important, and you need strong guarantees about processing. It’s designed for application integration and transactional workloads.
Now, contrast this with Event Hubs. Event Hubs is built for ingesting massive streams of events. Think of it like a firehose. It’s designed to handle millions of events per second from thousands of sources, often for telemetry, logging, or IoT data. The focus is on throughput and durability of the stream itself, not necessarily on individual message processing guarantees for a specific consumer.
Here’s Event Hubs sending a batch of events:
# Install Azure Event Hubs module if you haven't already
# Install-Module -Name Az.EventHubs -Scope CurrentUser
$eventHubNamespace = "your-eventhub-namespace.servicebus.windows.net"
$eventHubName = "my-eventhub"
$connectionString = "Endpoint=sb://{your-eventhub-namespace}.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SHARED_ACCESS_KEY"
# Create an Event Hubs producer client
$producer = New-AzEventHubsProducer -Namespace $eventHubNamespace -EventHubName $eventHubName -ConnectionString $connectionString
# Create a batch of events
$event1 = New-AzEventHubsEvent -Body "DeviceID: ABC, Temperature: 25.5"
$event2 = New-AzEventHubsEvent -Body "DeviceID: DEF, Temperature: 22.1"
$eventBatch = @($event1, $event2)
# Send the batch
$producer.Send($eventBatch)
Write-Host "Batch of events sent to Event Hub: $eventHubName"
And here’s a consumer (like Azure Stream Analytics or a custom application using the Event Hubs SDK) reading from a specific partition:
Event Hubs consumers typically operate on a consumer group and track their own progress (offset) within a partition. They don’t "complete" messages in the same way Service Bus does. Instead, they commit their current read position.
# Install Azure Event Hubs module if you haven't already
# Install-Module -Name Az.EventHubs -Scope CurrentUser
$eventHubNamespace = "your-eventhub-namespace.servicebus.windows.net"
$eventHubName = "my-eventhub"
$consumerGroupName = "$DefaultConsumerGroup" # Or your custom consumer group
$connectionString = "Endpoint=sb://{your-eventhub-namespace}.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=YOUR_SHARED_ACCESS_KEY"
# Create an Event Hubs consumer client
$consumer = New-AzEventHubsConsumer -Namespace $eventHubNamespace -EventHubName $eventHubName -ConsumerGroup $consumerGroupName -ConnectionString $connectionString
# Read events from a specific partition (e.g., partition 0)
# The SDK handles offset management, or you can manage it yourself for advanced scenarios.
$events = $consumer.Receive(100) # Read up to 100 events
if ($events) {
foreach ($event in $events) {
Write-Host "Received event: $($event.Body)"
# Process the event...
}
# The SDK's internal state or a separate checkpoint store would track the last read offset for this consumer group/partition.
Write-Host "$($events.Count) events processed."
} else {
Write-Host "No events received."
}
The mental model for Event Hubs is a durable, partitioned log. Data flows in, and consumers can read from any point in time from any partition. It’s designed for high-throughput telemetry and event streaming. Key characteristics include:
- Partitioning: Data is divided into partitions, allowing for parallel ingestion and consumption. This is key to its massive scale.
- Consumer Groups: Multiple applications or services can read from the same Event Hub independently, each maintaining its own reading position.
- Time-based retention: Events are kept for a configurable duration (e.g., 1 to 7 days, or longer with Archival to Blob Storage) and then automatically discarded.
- Ordered within a partition: Events are guaranteed to be in the order they were received within a single partition. Ordering across partitions is not guaranteed.
- "At-least-once" delivery: Consumers might receive the same event multiple times if they crash before committing their offset. The responsibility for deduplication often lies with the consumer application.
The most surprising thing about Event Hubs is that while it uses the Service Bus protocol under the hood (hence the .servicebus.windows.net endpoint), its operational semantics and pricing are entirely different, optimized for a stream processing paradigm rather than individual message delivery guarantees. You don’t "complete" a message in Event Hubs; you advance your reading offset.
When you’re deciding, ask yourself: do I need to ensure a specific piece of work is done exactly once, or do I need to ingest a massive volume of data for analysis or real-time processing? The former points to Service Bus, the latter to Event Hubs.
The next step after understanding these two is to explore how Azure Stream Analytics can efficiently consume from Event Hubs for real-time analytics, or how Durable Functions can leverage Service Bus queues for complex, stateful orchestrations.