📬 Part 4 — Sessions, Duplicate Detection & Transactions in Azure Service Bus with .NET
So far, we’ve covered:
👉 In Part 4, we’ll explore three advanced features:
- Sessions → ordered, FIFO processing
- Duplicate Detection → prevent double-processing
- Transactions → atomic send/receive across operations
🔹 1. Sessions — FIFO Message Processing
By default, Service Bus does not guarantee ordering — messages can arrive out of order if multiple consumers run.
💡 Sessions let you group related messages (conversation, workflow) so they are processed in order by a single consumer.
Example Use Case
- Order workflow:
- Step 1 → Payment authorized
- Step 2 → Inventory updated
- Step 3 → Invoice generated
- All steps for the same
OrderIdmust be processed in sequence.
Enabling Sessions
- When creating a queue or subscription, set RequiresSession = true.
az servicebus queue create -g myRg --namespace-name mysbnamespace -n orders-session-queue --enable-session true
Sending Session Messages
var sender = client.CreateSender("orders-session-queue");
var message = new ServiceBusMessage("Step 1: Payment authorized")
{
SessionId = "Order-123" // groups messages for this session
};
await sender.SendMessageAsync(message);
👉 All messages with SessionId = "Order-123" are delivered in order.
Receiving Session Messages
var sessionProcessor = client.CreateSessionProcessor("orders-session-queue", new ServiceBusSessionProcessorOptions
{
MaxConcurrentSessions = 5, // process multiple sessions in parallel
AutoCompleteMessages = false
});
sessionProcessor.ProcessMessageAsync += async args =>
{
Console.WriteLine($"[Session {args.Message.SessionId}] {args.Message.Body}");
await args.CompleteMessageAsync(args.Message);
};
sessionProcessor.ProcessErrorAsync += args =>
{
Console.WriteLine($"Session error: {args.Exception}");
return Task.CompletedTask;
};
await sessionProcessor.StartProcessingAsync();
💡 Service Bus locks an entire session for one processor at a time → ensuring FIFO ordering within that session.
🔹 2. Duplicate Detection
Sometimes producers accidentally send the same message twice (e.g., network retries). To prevent processing duplicates, enable duplicate detection on queues or topics.
Enabling Duplicate Detection
az servicebus queue create \
-g myRg --namespace-name mysbnamespace -n orders-dedup-queue \
--requires-duplicate-detection true \
--duplicate-detection-history-time-window PT10M
- Window:
PT10M= 10 minutes (ISO 8601 format). - Any message with the same
MessageIdin that time window is ignored.
Example in .NET
var sender = client.CreateSender("orders-dedup-queue");
var message1 = new ServiceBusMessage("Order Created") { MessageId = "Order-123" };
var message2 = new ServiceBusMessage("Order Created") { MessageId = "Order-123" }; // duplicate
await sender.SendMessagesAsync(new[] { message1, message2 });
💡 Only the first message is delivered. The second is silently dropped by Service Bus.
🔹 3. Transactions — Atomic Operations
Sometimes you need multiple Service Bus operations to succeed together or not at all. Example:
- Receive message from
orders-queue - Send event to
billing-queue - Send event to
inventory-queue
👉 Either all succeed or none do.
Example: Transaction in .NET
var sender1 = client.CreateSender("billing-queue");
var sender2 = client.CreateSender("inventory-queue");
var receiver = client.CreateReceiver("orders-queue");
ServiceBusReceivedMessage message = await receiver.ReceiveMessageAsync();
using var ts = await client.CreateTransactionAsync();
try
{
// Complete message within transaction
await receiver.CompleteMessageAsync(message, ts);
// Send dependent messages
await sender1.SendMessageAsync(new ServiceBusMessage("Billing event"), ts);
await sender2.SendMessageAsync(new ServiceBusMessage("Inventory event"), ts);
// Commit transaction
await client.CommitTransactionAsync(ts);
}
catch
{
await client.RollbackTransactionAsync(ts);
}
💡 Transactions ensure consistency across multiple queues/topics.
📌 Best Practices
- Sessions:
- Use when strict ordering is required (e.g., workflows, conversations).
- Keep sessions short-lived — don’t block others.
- Duplicate Detection:
- Always set
MessageId(GUID or business key). - Pick a history window that balances performance vs duplication risk.
- Always set
- Transactions:
- Use sparingly — they add overhead.
- Great for financial apps, workflows needing atomic guarantees.
🎯 Conclusion
In this final part, we covered advanced Service Bus features:
- ✅ Sessions for ordered FIFO workflows
- ✅ Duplicate Detection to avoid double-processing
- ✅ Transactions for atomic send/receive
With these tools, you can design resilient, reliable, and consistent .NET microservices that handle real-world complexities like ordering, idempotency, and consistency.
👉 That wraps up our 4-part series on Azure Service Bus + .NET Microservices!
- Part 1 → Queues + Worker
- Part 2 → Topics + Subscriptions
- Part 3 → DLQ + Retries + Monitoring
- Part 4 → Sessions + Deduplication + Transactions
Comments
Post a Comment