Azure Service Bus Premium tier provides enterprise-grade messaging with dedicated resources, large message support (up to 100MB), and VNET integration. Unlike the Standard tier (shared multi-tenant), Premium guarantees predictable performance for mission-critical workloads. This guide covers when to choose Premium, advanced features like Message Sessions and Duplicate Detection, and patterns for high-throughput financial transaction processing.
Premium vs Standard Tier
| Feature | Standard | Premium |
|---|---|---|
| Pricing | Pay per operation | Fixed (Messaging Units) |
| Max Message Size | 256 KB | 100 MB |
| Throughput | Variable (shared) | Dedicated capacity |
| VNET Integration | ❌ | ✅ Private Endpoints |
| Availability Zones | ❌ | ✅ |
| Geo-DR | ❌ | ✅ (Metadata only) |
Messaging Units Sizing
Premium namespaces are provisioned in Messaging Units (MU). Each MU provides approximately:
- 1 MU: ~1,000 messages/second (1KB messages)
- 2 MU: ~2,000 messages/second
- 4 MU: ~4,000 messages/second
For high-throughput workloads (100,000+ msg/sec), use multiple namespaces with a partitioning strategy.
Message Sessions: Ordered Processing
Sessions provide FIFO ordering per session ID. All messages with the same SessionId are processed by a single consumer in order—critical for order processing, user message threads, and IoT device telemetry.
flowchart LR
subgraph Producers
P1["Producer 1"]
P2["Producer 2"]
end
subgraph Queue ["Service Bus Queue (Sessions Enabled)"]
S1["Session: Customer-123"]
S2["Session: Customer-456"]
S3["Session: Customer-789"]
end
subgraph Consumers
C1["Consumer 1 (Locked to 123)"]
C2["Consumer 2 (Locked to 456)"]
C3["Consumer 3 (Locked to 789)"]
end
P1 -->|SessionId: 123| S1
P1 -->|SessionId: 456| S2
P2 -->|SessionId: 789| S3
S1 --> C1
S2 --> C2
S3 --> C3
style S1 fill:#C8E6C9,stroke:#2E7D32
// Producer: Set SessionId
var message = new ServiceBusMessage(orderJson)
{
SessionId = order.CustomerId, // All orders for this customer processed in order
MessageId = Guid.NewGuid().ToString()
};
await sender.SendMessageAsync(message);
// Consumer: Accept session and process
await using var processor = client.CreateSessionProcessor(queueName, new ServiceBusSessionProcessorOptions
{
MaxConcurrentSessions = 10, // Process 10 customers concurrently
MaxConcurrentCallsPerSession = 1 // But only 1 message per customer at a time
});
processor.ProcessMessageAsync += async args =>
{
var order = JsonSerializer.Deserialize<Order>(args.Message.Body);
await ProcessOrderAsync(order);
await args.CompleteMessageAsync(args.Message);
};
processor.ProcessErrorAsync += args =>
{
_logger.LogError(args.Exception, "Session processing failed");
return Task.CompletedTask;
};
await processor.StartProcessingAsync();
Duplicate Detection
Enable duplicate detection to prevent processing the same message twice (important for at-least-once delivery semantics):
resource queue 'Microsoft.ServiceBus/namespaces/queues@2022-01-01-preview' = {
parent: namespace
name: 'orders'
properties: {
requiresDuplicateDetection: true
duplicateDetectionHistoryTimeWindow: 'PT10M' // 10-minute window
requiresSession: true
deadLetteringOnMessageExpiration: true
maxDeliveryCount: 10
}
}
The MessageId property is used for deduplication. If a message with the same MessageId arrives within the detection window, it is silently discarded.
Dead Letter Queue Handling
Messages that fail processing (exceed MaxDeliveryCount) land in the Dead Letter Queue (DLQ). Production systems must monitor and process DLQ:
// Process dead-lettered messages
var dlqReceiver = client.CreateReceiver(queueName, new ServiceBusReceiverOptions
{
SubQueue = SubQueue.DeadLetter
});
await foreach (var message in dlqReceiver.ReceiveMessagesAsync())
{
var deadLetterReason = message.DeadLetterReason;
var deadLetterDescription = message.DeadLetterErrorDescription;
_logger.LogWarning("DLQ Message: {Reason} - {Description}", deadLetterReason, deadLetterDescription);
// Attempt remediation or forward to manual review
await ForwardToManualReviewAsync(message);
await dlqReceiver.CompleteMessageAsync(message);
}
VNET Integration with Private Endpoints
Premium tier supports Private Endpoints for secure, VNET-internal access:
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2022-01-01' = {
name: 'sb-private-endpoint'
location: location
properties: {
privateLinkServiceConnections: [
{
name: 'sb-connection'
properties: {
privateLinkServiceId: serviceBusNamespace.id
groupIds: ['namespace']
}
}
]
subnet: {
id: vnet::privateEndpointSubnet.id
}
}
}
// Disable public access
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' = {
properties: {
publicNetworkAccess: 'Disabled'
}
}
Key Takeaways
- Use Premium tier for dedicated capacity, large messages, and VNET integration
- Message Sessions provide FIFO ordering per partition key
- Enable Duplicate Detection for exactly-once semantics
- Monitor Dead Letter Queues for failed message processing
- Use Private Endpoints to eliminate public internet exposure
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.