AZ-204Chapter 64 of 102Objective 5.2

Service Bus Sessions and Duplicate Detection

This chapter covers two critical Azure Service Bus features: sessions and duplicate detection. These features are essential for building reliable, ordered message processing in distributed systems. On the AZ-204 exam, approximately 10-15% of questions on the Integrate domain (5.2) test your understanding of these concepts, including configuration, behavior, and common pitfalls. You will be expected to know default values, how sessions guarantee ordering, and how duplicate detection prevents message loss.

25 min read
Intermediate
Updated May 31, 2026

The Vending Machine with Order Numbers

Imagine a vending machine that sells sandwiches. Each sandwich has a unique order number printed on its wrapper. You insert money and press a button. The machine prints a receipt with that order number and starts preparing the sandwich. If your friend presses the same button at the exact same time, the machine might accidentally prepare two sandwiches for the same order number. But the machine has a rule: it checks if an order number has already been processed before starting a new one. It keeps a small list of recent order numbers (say the last 100). If the order number is already in the list, it rejects the duplicate and gives you a message that the order was already made. This is exactly how duplicate detection works in Service Bus. The machine also has a special feature: if you want to pick up your sandwich at a specific time, you can ask for a session. The machine groups all sandwiches for the same session (e.g., all orders for "John's lunch") in a bin. You can then pick up the entire bin at once, ensuring you get all related sandwiches together. Without sessions, you might get your sandwich but your drink might be in a different bin. Sessions guarantee that all messages with the same session ID are processed in order and by the same consumer.

How It Actually Works

What Are Service Bus Sessions?

Service Bus sessions enable ordered, grouped processing of messages. A session is a logical grouping of messages that share a SessionId property. All messages with the same SessionId are guaranteed to be delivered in order (FIFO) and are locked to a single consumer until that consumer completes or abandons them. This is crucial for scenarios where message order matters, such as processing bank transactions or IoT device telemetry.

How Sessions Work Internally

When a queue or subscription has RequiresSession set to true, messages must have a SessionId. The broker maintains a session state that persists across messages. A consumer must accept a session by calling AcceptMessageSessionAsync() (or using the SessionProcessor in the SDK). The consumer then receives all messages for that session exclusively. The session lock is renewed automatically by the SDK (default lock duration is 1 minute, configurable up to 5 minutes). If the consumer fails, the session becomes available to other consumers after the lock expires.

Key Components and Defaults

SessionId: String property on the message. Messages with null or empty SessionId are rejected if RequiresSession is true.

Session State: A byte array that can be used to store processing state (e.g., checkpoint). Must be serialized/deserialized by the application.

Session Lock Duration: Default 1 minute. Can be set between 15 seconds and 5 minutes on the queue/topic.

MaxConcurrentSessions: For SessionProcessor, controls how many sessions can be processed simultaneously (default 1).

Message Sessions: The number of sessions is unlimited, but each session can have up to 256 KB of state.

Duplicate Detection

Duplicate detection ensures that messages with the same MessageId are not delivered more than once within a specified time window. The broker maintains a history of recently processed MessageIds. If a new message arrives with a MessageId that matches one in the history, it is silently discarded (accepted but not enqueued).

How Duplicate Detection Works

When a message is sent, the broker checks if its MessageId exists in a duplicate detection history for that queue/topic. The history is an in-memory cache that persists for a configurable duplicate detection history time window (default 10 minutes, max 7 days). If found, the message is not enqueued, but the send operation returns success (to avoid sender confusion). If not found, the message is enqueued and its MessageId is added to the history.

Key Values and Defaults

DuplicateDetectionHistoryTimeWindow: Default 10 minutes. Minimum 20 seconds, maximum 7 days. Setting it too short increases risk of duplicates; too long increases memory usage.

RequiresDuplicateDetection: Boolean property on queue/topic. Must be set at creation time; cannot be changed.

MessageId: Application-defined string. Must be unique within the time window. If not set, Service Bus auto-generates a GUID.

Configuration and Verification

Using Azure CLI:

# Create a queue with sessions and duplicate detection
az servicebus queue create --resource-group myRG --namespace-name myNS \
  --name myQueue --requires-session true --requires-duplicate-detection true \
  --duplicate-detection-history-time-window PT10M

Using C# SDK:

// Send message with session and duplicate detection
var message = new ServiceBusMessage("Hello")
{
    SessionId = "session1",
    MessageId = Guid.NewGuid().ToString()
};
await sender.SendMessageAsync(message);

// Receive messages from a session
var sessionReceiver = await client.AcceptSessionAsync("session1");
var message = await sessionReceiver.ReceiveMessageAsync();

Interaction with Related Technologies

Service Bus Queues vs Topics: Sessions and duplicate detection work identically on queues and subscriptions.

Auto-Forwarding: Messages forwarded from one queue to another retain their MessageId and SessionId. Duplicate detection on the destination can catch duplicates if the source has a different time window.

Dead-Lettering: Messages that fail processing can be dead-lettered. Sessions can be dead-lettered as a whole using SessionState.

Partitioning: In partitioned queues, duplicate detection history is per-partition. The same MessageId sent to different partitions may not be detected as duplicate. Partitioning is legacy; use premium tier for high throughput.

Performance Considerations

Duplicate detection adds overhead: each message requires a lookup in the history. For high-throughput scenarios, consider whether duplicates are tolerable.

Session state should be kept small (under 256 KB) to avoid latency.

MaxConcurrentSessions should be tuned based on CPU and network capacity. Too many concurrent sessions can overwhelm the consumer.

Common Pitfalls

Forgetting to set SessionId on messages when RequiresSession is true — messages are rejected.

Setting duplicate detection time window too short — duplicates may appear after window expires.

Not handling session lock renewal — long processing can cause lock loss.

Using auto-generated MessageId — if sender retries, each retry generates a new MessageId, defeating duplicate detection. Always set a deterministic MessageId for idempotent sends.

Walk-Through

1

Configure Queue/Topic for Sessions

Set RequiresSession to true at creation time. This cannot be changed later. The queue/topic will reject messages without a SessionId. Use Azure Portal, CLI, or ARM template. For example, using CLI: `az servicebus queue create --requires-session true`. Also set session lock duration (default 1 minute) and max concurrent sessions on the consumer.

2

Set SessionId on Messages

When sending messages, assign a SessionId string that groups related messages. Messages with the same SessionId will be delivered in order and locked to one consumer. If you don't set SessionId and RequiresSession is true, the send operation fails with a BadRequest error. Use a business key like CustomerId or DeviceId.

3

Accept a Session on Consumer Side

The consumer must accept a session using `AcceptMessageSessionAsync(sessionId)` or use a `ServiceBusSessionProcessor`. The SDK handles session acceptance and lock renewal. If no session is available, the call blocks until a session becomes available or timeout occurs. The consumer then receives messages exclusively for that session.

4

Process Messages in Order

Once a session is accepted, messages are received in FIFO order. The consumer processes each message and completes, defers, or dead-letters it. The session lock is automatically renewed by the SDK. If processing fails, the consumer can abandon the message, making it available for redelivery within the same session.

5

Configure Duplicate Detection

Set RequiresDuplicateDetection to true at queue/topic creation. Configure DuplicateDetectionHistoryTimeWindow (default 10 minutes). Ensure each message has a unique MessageId. The broker will silently discard duplicates. Use a deterministic MessageId for retries (e.g., transaction ID).

6

Send Messages with Unique MessageId

Assign a MessageId that is unique within the detection time window. If the sender retries, it must send the same MessageId. The broker checks the history; if found, the message is not enqueued but send returns success. If no MessageId is set, the broker assigns a GUID, which makes retries generate new MessageIds and bypass duplicate detection.

What This Looks Like on the Job

E-Commerce Order Processing

An online retailer uses Service Bus queues to process orders. Each order generates multiple messages: payment, inventory, shipping. Using sessions with the OrderId as SessionId ensures all messages for an order are processed by the same consumer in order. Duplicate detection prevents double-charging if the payment gateway retries. The queue is configured with RequiresSession=true and RequiresDuplicateDetection=true. The duplicate detection time window is set to 1 hour to cover retry windows. The consumer uses a SessionProcessor with MaxConcurrentSessions=5 to handle multiple orders simultaneously. Misconfiguration: if the time window is too short (e.g., 1 minute), a retry after 2 minutes could cause duplicate payment.

IoT Telemetry Ingestion

A fleet management company collects telemetry from thousands of vehicles. Each vehicle has a unique device ID. Messages from a vehicle must be processed in order to track location history. Sessions with DeviceId as SessionId guarantee ordering. Duplicate detection is enabled with a 5-minute window to handle intermittent network retries. The consumer scales out by accepting different sessions. Performance consideration: session state stores the last known location to enable incremental updates. If state grows too large (over 256 KB), it can cause throttling.

Banking Transaction Processing

A bank processes fund transfers using Service Bus topics. Each transfer generates a debit and credit message. Sessions with TransactionId ensure atomic processing: the consumer completes both messages or dead-letters the session. Duplicate detection prevents duplicate debits. The duplicate detection window is set to 7 days (maximum) to cover settlement periods. The consumer must handle session lock renewal for long-running transactions. Common issue: if the consumer crashes mid-session, the session becomes available to another consumer, but the session state (e.g., 'debit done') must be used to avoid reprocessing the debit.

How AZ-204 Actually Tests This

What AZ-204 Tests

Objective 5.2: Implement message processing with Service Bus. Sub-areas: sessions and duplicate detection.

Question types: Multiple-choice scenarios where you choose correct configuration, identify why a feature is needed, or pick correct default values.

Common Wrong Answers

1.

Sessions are for load balancing: Wrong. Sessions ensure ordering and exclusive processing, not load balancing. Load balancing is achieved by multiple consumers accepting different sessions.

2.

Duplicate detection prevents duplicate processing forever: Wrong. It only works within the configured time window (default 10 minutes). After that, duplicates can occur.

3.

Setting RequiresSession on an existing queue is possible: Wrong. It must be set at creation time.

4.

MessageId is auto-generated and always unique: Wrong. If you don't set it, the broker assigns a GUID, but that defeats duplicate detection for retries.

Specific Numbers and Terms

DuplicateDetectionHistoryTimeWindow default: 10 minutes. Range: 20 seconds to 7 days.

Session lock duration default: 1 minute. Range: 15 seconds to 5 minutes.

MaxConcurrentSessions default: 1.

Session state max size: 256 KB.

RequiresSession: Cannot be changed after creation.

RequiresDuplicateDetection: Cannot be changed after creation.

Edge Cases

Partitioned queues: Duplicate detection is per-partition. In high-throughput scenarios, duplicates may occur if the same MessageId is sent to different partitions. Use premium tier for global duplicate detection.

Auto-forwarding: If queue A forwards to queue B, and both have duplicate detection, a message sent to A may be detected as duplicate on B if the same MessageId was already processed by B.

Session state: If you don't set session state, it remains null. The exam may test that you need to serialize/deserialize manually.

How to Eliminate Wrong Answers

If the question mentions 'ordering' or 'FIFO', sessions are likely required.

If the question mentions 'idempotent retry' or 'prevent duplicates', duplicate detection is the answer.

If the question asks about changing RequiresSession after creation, the answer is 'No, recreate the queue'.

Always check the time window: if the scenario involves retries over hours, the default 10 minutes may be too short.

Key Takeaways

Sessions guarantee ordered processing: all messages with the same SessionId are delivered in FIFO order to a single consumer.

Duplicate detection uses MessageId and a history window (default 10 minutes) to silently discard duplicates.

Both RequiresSession and RequiresDuplicateDetection are immutable queue/topic properties — set at creation only.

Session lock duration default is 1 minute, configurable from 15 seconds to 5 minutes.

Session state max size is 256 KB — use it for checkpointing, not large payloads.

For duplicate detection to work with retries, always set a deterministic MessageId (e.g., transaction ID).

Partitioned queues have per-partition duplicate detection — duplicates can occur across partitions in non-premium tiers.

MaxConcurrentSessions default is 1 — increase for higher throughput.

Auto-forwarding preserves SessionId and MessageId — duplicate detection can cascade.

Dead-lettering a session: use session state to track progress and abandon the session to trigger redelivery.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

Service Bus Sessions

Groups messages with same SessionId for ordered processing

Requires RequiresSession=true at creation

Enables FIFO delivery within a session

Locks session to one consumer at a time

Supports session state for checkpointing

Duplicate Detection

Prevents duplicate messages within time window

Requires RequiresDuplicateDetection=true at creation

Uses MessageId to identify duplicates

Silently discards duplicate messages

History time window configurable (20s to 7 days)

Watch Out for These

Mistake

Sessions guarantee that messages are delivered to the same consumer instance.

Correct

Sessions guarantee that messages with the same SessionId are processed exclusively by one consumer at a time, but not necessarily the same instance. If the consumer crashes or releases the session, another consumer can pick it up. The session state can be used to preserve processing progress.

Mistake

Duplicate detection prevents all duplicates forever.

Correct

Duplicate detection only works within the configured history time window (default 10 minutes). After that window expires, the MessageId is removed from history and a duplicate with the same MessageId will be accepted as a new message.

Mistake

You can enable sessions on an existing queue by updating its properties.

Correct

RequiresSession is a creation-time property. You cannot modify it on an existing queue or topic. You must delete and recreate the queue/topic with RequiresSession=true.

Mistake

MessageId is always set automatically by Service Bus.

Correct

If you do not set MessageId on a message, Service Bus auto-generates a GUID. However, for duplicate detection to work with retries, you must set a deterministic MessageId yourself. Otherwise, each retry gets a new GUID and duplicates are not detected.

Mistake

Session lock duration can be changed per message.

Correct

Session lock duration is set at the queue/topic level (default 1 minute). It applies to all sessions. You cannot change it per message. The SDK automatically renews the lock, but you can control the renewal interval.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

Can I enable sessions on an existing Service Bus queue?

No. The RequiresSession property can only be set when the queue is created. To use sessions, you must delete the existing queue and create a new one with RequiresSession=true. Alternatively, create a new queue and redirect producers/consumers.

What happens if I send a message without a SessionId to a session-enabled queue?

The message is rejected with a BadRequest error (HTTP 400). The broker requires that all messages have a non-null SessionId when RequiresSession is true. The send operation will fail and the message is not enqueued.

How long does duplicate detection remember MessageIds?

The default is 10 minutes. You can configure it between 20 seconds and 7 days using the DuplicateDetectionHistoryTimeWindow property. After the window expires, the MessageId is removed from history and a duplicate can be accepted.

Can I use sessions and duplicate detection together?

Yes, they are independent features. You can enable both on the same queue or topic. Sessions handle ordering and exclusive processing; duplicate detection prevents duplicate messages. They are often used together in transactional scenarios.

What is the purpose of session state?

Session state allows you to store processing progress (e.g., last processed message sequence number) as a byte array. This is useful for long-running sessions where the consumer may crash and resume from the saved state. The state is stored in the broker and can be up to 256 KB.

How do I handle session lock expiry?

The Service Bus SDK automatically renews the session lock. You can configure the lock duration on the queue/topic (default 1 minute). For long processing, ensure the lock duration is sufficient or implement manual renewal using `RenewSessionLockAsync()`. If the lock expires, the session becomes available to other consumers.

Does duplicate detection work across partitioned queues?

In partitioned queues (standard tier), duplicate detection history is maintained per partition. A message with the same MessageId sent to different partitions may not be detected as duplicate. Use premium tier for global duplicate detection across all partitions.

Terms Worth Knowing

Ready to put this to the test?

You've just covered Service Bus Sessions and Duplicate Detection — now see how well it sticks with free AZ-204 practice questions. Full explanations included, no account needed.

Done with this chapter?