Cloud / Azure Service Bus Interview questions
Last updated
1. What is Azure Service Bus?
Azure Service Bus is a fully managed enterprise message broker. Applications send messages to it, and other applications pick them up later, so the two sides never have to be online at the same time or know anything about each other.
It offers queues for point-to-point messaging and topics for publish/subscribe. On top of that you get dead-lettering, sessions for ordering, transactions, duplicate detection and scheduled delivery, which is why it is the usual pick for business-critical flows like order processing.
Clients connect to a namespace endpoint such as myns.servicebus.windows.net over AMQP 1.0 or HTTPS.
Take quiz
high-throughput telemetry streaming platform
managed relational database for events
fully managed enterprise message broker
serverless workflow designer
MQTT 3.1
SMTP
gRPC streaming
AMQP 1.0
2. What are the main messaging entities in Azure Service Bus?
Service Bus has a small set of building blocks. Everything lives inside a namespace.
- Namespace - the container and endpoint that holds all your entities.
- Queue - stores messages for a single logical consumer (point-to-point).
- Topic - accepts messages from publishers and fans them out.
- Subscription - a virtual queue under a topic that receives copies of matching messages.
- Rule - a filter (and optional action) that decides which topic messages a subscription gets.
Each queue and subscription also has a built-in dead-letter sub-queue for messages that cannot be processed.
Take quiz
Namespace
Rule
Queue
Subscription
Its rules (filters)
The namespace's pricing tier
The sender's SAS policy
The queue's lock duration
3. What is a Service Bus queue?
A queue is a durable, broker-hosted buffer that delivers each message to one consumer. Senders add messages at one end, and receivers take them from the other, normally in first-in-first-out order.
If several receivers listen on the same queue they act as competing consumers: each message goes to exactly one of them, so you scale processing just by adding receivers.
Because the queue stores messages until they are settled, it also smooths out traffic spikes. This is called queue-based load leveling.
Take quiz
Exactly one
All receivers attached to the queue
Only the first and last receiver
One per subscription
It compresses messages to cut traffic
It buffers bursts so consumers work at their own pace
It automatically adds consumers on every spike
It removes the need for retries
4. What are topics and subscriptions in Service Bus?
A topic is the publish side of publish/subscribe messaging. A sender posts one message to the topic and does not care who reads it.
Each subscription on the topic behaves like its own virtual queue. It receives a copy of every message that passes its rules, and consumers read from the subscription independently, at their own speed.
For example, an OrderPlaced topic can feed a billing subscription, a shipping subscription and an analytics subscription, with no change on the publisher.
Take quiz
A single shared copy removed after the first read
Its own copy of every matching message
Only messages that match no rule
Messages handed out round-robin across subscriptions
Point-to-point only
Request/stream replay
Publish/subscribe
Batch ETL
5. What are the Azure Service Bus pricing tiers?
Service Bus comes in three tiers, chosen per namespace.
| Tier | Entities | Max message size | Capacity model |
| Basic | Queues only | 256 KB | Shared, pay per operation |
| Standard | Queues and topics | 256 KB | Shared, base charge plus operations |
| Premium | Queues and topics | Up to 100 MB | Dedicated messaging units |
Premium also adds private endpoints, VNet integration, geo-disaster recovery, customer-managed keys and predictable latency. Use Basic for simple queues, Standard for most apps that need topics, and Premium when isolation or throughput guarantees matter.
Take quiz
Standard
Premium
Basic
None, all tiers support topics
Throughput units
DTUs
Request units
Messaging units
6. What is a Service Bus namespace?
A namespace is the top-level container for your Service Bus queues and topics. It gives you a unique fully qualified domain name, <name>.servicebus.windows.net, which clients use to connect.
Many settings are decided at this level: the pricing tier, region, network rules, encryption options and namespace-wide shared access policies. Entities inside it inherit that environment.
A common practice is to keep one namespace per environment or per bounded workload, so one noisy workload cannot affect another.
Namespace names are globally unique, and access control can be applied here or narrowed down to a single queue, topic or subscription.
Take quiz
On each message
On each subscription
On each SAS key
On the namespace
A unique FQDN endpoint for its entities
A single FIFO queue
A filter expression for subscriptions
A dead-letter policy for the whole tenant
7. What are the properties of a Service Bus message?
A message has a body (opaque bytes, often JSON) plus two kinds of metadata.
- System properties -
MessageId,CorrelationId,SessionId,ReplyTo,Subject,ContentType,TimeToLive,ScheduledEnqueueTime,PartitionKey. - Broker-assigned -
SequenceNumber,EnqueuedTime,DeliveryCount,LockToken. - Application properties - your own key/value pairs, handy for routing and filters.
The broker never inspects the body, so filters work on the properties.
Keep the body small. Anything you need for routing, such as region or message type, belongs in application properties so filters never have to parse the payload.
Take quiz
ApplicationProperties
SequenceNumber
LockToken
DeliveryCount
MessageId
SequenceNumber
Subject
TimeToLive
8. What are the two receive modes in Service Bus?
Receivers pick a settlement behavior when they connect.
| Peek-lock (default) | Receive-and-delete |
| Message is locked, then the app completes, abandons, defers or dead-letters it. | Message is removed as soon as it is delivered. |
| At-least-once delivery. A crash means redelivery. | At-most-once delivery. A crash means the message is lost. |
| Use for anything that must not be lost. | Use only when losing a message is acceptable. |
Peek-lock is the right choice for almost every business workload.
In peek-lock mode the app must settle every message. If it forgets, the lock expires and the message returns, so always complete or abandon in a finally-style path.
Take quiz
Receive-and-delete
Peek-lock
Deferred mode
Session-only mode
Redelivered after the lock expires
Moved to the DLQ automatically
Lost
Kept as deferred
9. What is a dead-letter queue in Service Bus?
Every queue and subscription has a secondary sub-queue, the dead-letter queue (DLQ), where messages that cannot be delivered or processed are parked instead of being lost.
The path is <queue>/$deadletterqueue, or <topic>/Subscriptions/<sub>/$deadletterqueue for subscriptions.
The broker moves messages there when MaxDeliveryCount is exceeded or, if enabled, when the TTL expires. Applications can also dead-letter explicitly with a reason and description. Nothing purges the DLQ automatically, so you must monitor and drain it.
A message dead-lettered by the broker carries DeadLetterReason and DeadLetterErrorDescription properties, so you can see why it failed without opening logs.
Take quiz
orders/deadletter
A separate queue named orders-dlq that you must create
orders/$deadletterqueue
$system/orders/dlq
Yes, after 7 days
Yes, when the original TTL elapses
Yes, when the namespace restarts
No, they stay until you receive or delete them
10. What is message time-to-live (TTL) in Service Bus?
TTL is how long a message may stay in an entity before it expires. Each queue or subscription has a DefaultMessageTimeToLive, and a sender can set a shorter TimeToLive on an individual message.
If a message-level TTL is longer than the entity default, the entity value wins. Once a message expires, it is silently dropped, unless dead-lettering on expiration is enabled, in which case it moves to the DLQ.
Short TTLs suit time-sensitive data like OTP codes or price quotes that are useless if delivered late.
Take quiz
It always goes to the DLQ
It is redelivered with DeliveryCount reset
It becomes a deferred message
It is silently removed
Capped to the entity's TTL
Honored and overrides the entity
Rejected with an exception on send
Converted to a scheduled message
11. What are scheduled messages in Service Bus?
A scheduled message is sent now but becomes visible to receivers only at a future time. You set ScheduledEnqueueTime on the message, or call ScheduleMessageAsync.
The call returns a sequence number. If plans change, pass that number to CancelScheduledMessageAsync before the time arrives.
Typical uses are reminder emails, delayed retries with back-off, and timeouts in long-running workflows.
A scheduled message sits invisible in the entity until its time arrives, then behaves like any other message. It still counts toward entity size while waiting, so very large scheduled backlogs can use up quota.
Take quiz
A sequence number
A lock token
A session ID
A rule name
EnqueuedTimeUtc
ScheduledEnqueueTime
LockedUntilUtc
ExpiresAtUtc
12. What is message deferral in Service Bus?
Deferral lets a receiver set a message aside when it cannot handle it yet, for example when messages arrive out of business order. The message stays in the queue but is skipped by normal receive calls.
The app calls DeferMessageAsync and must remember the SequenceNumber. Later it fetches the message with ReceiveDeferredMessageAsync using that number.
Deferred messages are still subject to TTL, and if the sequence number is lost there is no easy way to find them again.
Deferral differs from abandon: abandoning makes the message immediately deliverable again, while deferral hides it from normal receives until you ask for it by number.
Take quiz
With a normal ReceiveMessagesAsync call
By its SequenceNumber through the deferred-receive call
By reusing the old lock token
From a $deferred sub-queue
Service Bus keeps a list per receiver
Azure Monitor
The application
The original sender
13. What are Service Bus sessions?
Sessions group related messages so they are handled together and in order. The sender stamps every related message with the same SessionId, for example an order ID or customer ID.
A receiver accepts a session and takes an exclusive lock on it. While it holds the lock, it gets that session's messages in FIFO order, and no other receiver can read them. Sessions also carry session state, a small blob for storing progress.
The queue or subscription must be created with sessions enabled, which requires the Standard or Premium tier.
Take quiz
CorrelationId
PartitionKey
SessionId
ReplyTo
Any number, in round-robin
Two, primary and standby
All of them, each gets a copy
One
14. How do you send a message using the.NET SDK?
Create a ServiceBusClient, get a sender for the entity, and call SendMessageAsync. Prefer Microsoft Entra credentials over connection strings.
A single send is limited by the tier's message size (256 KB on Standard). The sender should be created once per entity and shared, since it holds an AMQP link.
await using var client = new ServiceBusClient( "myns.servicebus.windows.net", new DefaultAzureCredential()); ServiceBusSender sender = client.CreateSender("orders"); var msg = new ServiceBusMessage(JsonSerializer.Serialize(order)) { MessageId = order.Id.ToString(), ContentType = "application/json", Subject = "OrderCreated" }; await sender.SendMessageAsync(msg);
For many messages, use CreateMessageBatchAsync and TryAddMessage instead. Create the client once and reuse it.
Take quiz
Embedding a Manage SAS key in source
Anonymous access
Putting the key in a query string
DefaultAzureCredential with a managed identity
It supports duplicate detection and tracing
It encrypts the body
It sets the lock duration
It chooses the sub-queue
15. How do you receive messages using ServiceBusProcessor?
ServiceBusProcessor is the recommended way to consume messages. It runs a receive loop, calls your handler, renews locks and handles retries on transient errors.
var processor = client.CreateProcessor("orders", new ServiceBusProcessorOptions { MaxConcurrentCalls = 8, AutoCompleteMessages = true }); processor.ProcessMessageAsync += async args => { var body = args.Message.Body.ToString(); await HandleAsync(body); // throw to abandon }; processor.ProcessErrorAsync += args => { Console.WriteLine(args.Exception); return Task.CompletedTask; }; await processor.StartProcessingAsync();
If the handler returns normally, the message is completed. If it throws, the message is abandoned and retried.
Take quiz
ProcessErrorAsync
ProcessLockLostAsync
ProcessCompleteAsync
ProcessDeadLetterAsync
As soon as it is received
When the handler returns without an exception
After the lock duration passes
After it is copied to the DLQ
16. What is duplicate detection in Service Bus?
Duplicate detection makes the broker drop a message if another message with the same MessageId was already accepted within a time window. It protects you when a sender retries after a timeout and ends up sending twice.
It must be turned on when the queue or topic is created. The history window defaults to 10 minutes and can range from 20 seconds to 7 days.
The duplicate is accepted by the API but silently discarded, so the sender sees no error. Choose a stable ID, such as the business key, not a random GUID per attempt.
Take quiz
SequenceNumber
MessageId
LockToken
CorrelationId
1 minute
24 hours
10 minutes
7 days
17. How do you authenticate to Azure Service Bus?
There are two options.
- Microsoft Entra ID - assign a role such as Azure Service Bus Data Sender, Data Receiver or Data Owner to a user or managed identity. No secret is stored.
- Shared Access Signature (SAS) - a policy with
Send,Listenand/orManagerights produces keys, connection strings or time-limited tokens.
Entra ID is the recommended option for production. You can even disable SAS (local auth) on the namespace to enforce it.
Scope matters. Assigning a role at queue level gives an app access to that queue only, rather than the whole namespace.
Take quiz
Azure Service Bus Data Receiver
Azure Service Bus Data Owner
Azure Service Bus Data Sender
Contributor
Read, Write, Execute
Publish, Subscribe, Admin
Peek, Lock, Settle
Send, Listen, Manage
18. What are subscription rules and filters in Service Bus?
A subscription rule has a filter that decides whether a topic message is copied to that subscription, and an optional action that can modify properties on the copy.
| Filter type | Matches on |
| Boolean (True/False) | Everything or nothing |
| SQL filter | A SQL-92 style expression over properties |
| Correlation filter | Equality on listed system or custom properties |
New subscriptions get a $Default rule with a true filter, so they receive all messages until you replace it.
Rule actions run on the copy only. For example, a SQL action can set a property such as routed=true without changing the message other subscriptions see.
Take quiz
Boolean filter
SQL filter
Session filter
Correlation filter
No messages
All messages
Only dead-lettered messages
Only scheduled messages
19. What is the difference between queues and topics?
A queue delivers each message to one logical consumer. A topic delivers a copy to every subscription whose filter matches.
| Queue | Topic + subscriptions |
| Point-to-point | Publish/subscribe |
| Competing consumers share the work | Each subscription is an independent consumer group |
| No filtering | Rules filter and enrich per subscription |
| Available in all tiers | Standard and Premium only |
If one subscription is enough, a queue is simpler. Pick a topic when several systems must react to the same event.
One more difference is cost and operations: every subscription adds its own storage and delivery work, so a topic with many subscriptions costs more than a single queue.
Take quiz
Standard and Premium
Basic and Standard
Only Premium
All three tiers
One queue with three consumers
A topic with three subscriptions
Three separate namespaces
A queue with sessions enabled
20. What is the difference between Service Bus and Storage Queues?
Both queue messages, but Service Bus is a full broker while Storage Queues is a simple, very large, low-cost queue.
| Feature | Service Bus | Storage Queues |
| Max message size | 256 KB (100 MB Premium) | 64 KB |
| Topics / pub-sub | Yes | No |
| Ordering guarantee | FIFO with sessions | Not guaranteed |
| Dead-letter queue | Built in | Manual |
| Duplicate detection, transactions | Yes | No |
Choose Storage Queues for simple background jobs and huge backlogs. Choose Service Bus when you need ordering, pub/sub, or reliable enterprise semantics.
Also consider message lifetime. Storage Queue messages are removed on delete, while Service Bus gives you explicit complete, abandon, defer and dead-letter outcomes, which matters for auditing failures.
Take quiz
Storage Queues
Service Bus
Both identically
Neither
Service Bus Premium
Event Hubs
Storage Queues
Service Bus topics with sessions
21. When should you use Service Bus over Event Hubs or Event Grid?
Match the service to the intent of the message.
| Service | Intent | Consumption |
| Service Bus | Commands and business messages that must be processed | Broker tracks each message and the consumer settles it |
| Event Hubs | High-volume event streams such as telemetry and logs | Consumers read partitions and checkpoint an offset |
| Event Grid | Reactive notifications about something that happened | Push delivery with retries to webhooks or handlers |
Use Service Bus when you need guaranteed processing, ordering, dead-lettering or transactions. Use Event Hubs for streaming analytics, and Event Grid for lightweight event routing.
They are often combined. For example, Event Hubs ingests raw telemetry, a processor turns interesting readings into commands, and Service Bus delivers those commands reliably to workers.
Take quiz
Service Bus queues
Event Grid
Event Hubs
Storage Queues
Event Hubs
Event Grid
Azure Monitor alerts
Service Bus
22. What happens when a peek-lock message lock expires?
If the receiver neither completes nor abandons the message before the lock expires, the broker releases it and makes it available again. The DeliveryCount goes up by one.
The original receiver's later CompleteMessageAsync call fails with a lock-lost error, so the work it did may be repeated by another consumer.
The default lock duration is 1 minute, with a maximum of 5 minutes. ServiceBusProcessor renews the lock automatically up to MaxAutoLockRenewalDuration, so long handlers should raise that value rather than just extending the lock.
A practical rule: set lock duration just above the typical handling time, let the processor auto-renew for slow outliers, and keep handlers idempotent because a redelivery may still occur.
Take quiz
30 seconds
10 minutes
No lock by default
1 minute
It becomes available for delivery again
It is deleted
It goes straight to the DLQ
It is deferred automatically
23. How does a message end up in the dead-letter queue?
There are a few paths into the DLQ.
- MaxDeliveryCountExceeded - the message was delivered the maximum number of times (default 10) without being completed.
- TTLExpiredException - the TTL elapsed and dead-lettering on expiration is enabled.
- Explicit - your code calls
DeadLetterMessageAsyncwith a reason and description, e.g. for a malformed payload. - Filter errors - on subscriptions, a rule evaluation failure if that option is on.
The reason and description are stored as properties on the dead-lettered message, which makes triage far easier.
The delivery count decides the first case, so a handler that throws on every attempt reaches the DLQ after ten tries by default, which is why poison messages stop looping.
Take quiz
10
3
5
Unlimited
TTLExpiredException
MaxDeliveryCountExceeded
HeaderSizeExceeded
SessionLockLost
24. How do you process dead-lettered messages?
Open a receiver on the dead-letter sub-queue, inspect why each message failed, then fix, resubmit or discard it.
Many teams run a small repair tool or Function that reads the DLQ, logs the reason, and resubmits messages after a bug fix. Always alert on the DLQ count so this does not go unnoticed.
var dlq = client.CreateReceiver("orders", new ServiceBusReceiverOptions { SubQueue = SubQueue.DeadLetter }); await foreach (var m in dlq.ReceiveMessagesAsync()) { var reason = m.DeadLetterReason; var detail = m.DeadLetterErrorDescription; // log, repair payload, then resend a NEW message await sender.SendMessageAsync(new ServiceBusMessage(m)); await dlq.CompleteMessageAsync(m); }
Resend as a new message rather than trying to move the old one, and complete the DLQ copy only after the resend succeeds. Dead-letter messages count against the entity's size quota.
Take quiz
ReceiveMode.DeadLetter
SubQueue = SubQueue.DeadLetter
EntityPath + '/dlq'
IsDeadLetter = true on the sender
LockToken and SequenceNumber
ReplyTo and Subject
DeadLetterReason and DeadLetterErrorDescription
EnqueuedTime and PartitionKey
25. How does Service Bus guarantee FIFO ordering?
Strict FIFO is guaranteed per session. The sender sets the same SessionId on related messages and sends them in order. The receiver locks that session and processes it sequentially.
Without sessions, a queue delivers roughly in order, but with several competing consumers, retries or abandons, completion order is not guaranteed.
The sender side matters too. Send ordered messages from one sender sequentially, rather than firing concurrent async sends that can arrive swapped.
If you need both order and scale, use many sessions. Each session is ordered, while different sessions run in parallel across receivers. Also enable duplicate detection if senders may retry, so a repeated send cannot insert a message twice into the ordered stream.
Take quiz
Across the whole namespace
Across all subscriptions
Within a session
Only in Basic tier
The broker sorts by message size
Messages are stored randomly
SAS tokens reorder them
Messages are processed concurrently and may be retried
26. Why do we use correlation filters instead of SQL filters?
A correlation filter matches by equality on one or more properties, such as Subject, CorrelationId or a custom property. All listed conditions must match (logical AND).
It is cheaper for the broker to evaluate than a SQL expression, so it scales better when a topic has many subscriptions. SQL filters are still the choice when you need LIKE, IN, comparisons or OR logic.
When a filter combines region and message type, correlation filters can match both with a single rule, which stays cheap even with hundreds of subscriptions.
await admin.CreateRuleAsync("orders", "eu-sub", new CreateRuleOptions("EuOnly", new CorrelationRuleFilter { ApplicationProperties = { ["region"] = "EU" } }));
Take quiz
OR
XOR
Whichever matches first
AND
SQL filter
Correlation filter
Boolean filter
None, it is impossible
27. How does auto-forwarding work in Service Bus?
Auto-forwarding makes the broker automatically move messages from a queue or subscription to another queue or topic in the same namespace. You set ForwardTo on the source.
It is useful for fan-in (many subscriptions into one queue), for chaining a subscription to a queue to get a single consumer, and for separating a processing pipeline into stages.
Chains can be up to four hops deep. The identity that creates the forwarding needs Send permission on the destination, and ForwardDeadLetteredMessagesTo can do the same for dead-lettered messages.
Typical example: a topic with several subscriptions, each forwarded to its own queue, so each service can use queue features like sessions or independent dead-letter handling.
Take quiz
Four
One
Ten
Unlimited
In any namespace in the region
In the same namespace
In any Azure subscription
In a Storage account
28. How do Service Bus transactions work?
A transaction groups several operations - receive, complete, send, defer, dead-letter - so they either all succeed or all roll back. In .NET you wrap them in a TransactionScope with async flow enabled.
Because the work is committed together, a failed send after a complete rolls the complete back, and the original message stays available for retry. Keep transactions short, since they hold locks.
using var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled); await receiver.CompleteMessageAsync(msg); await sender.SendMessageAsync(next); ts.Complete();
Operations can span entities in the same namespace when EnableCrossEntityTransactions is set. They cannot span namespaces or include your database, which is why patterns like the outbox exist.
Take quiz
Yes, automatically
No
Yes, in Premium only
Yes, if using Peek-lock
EnableBatchedOperations
RequiresSession
EnableCrossEntityTransactions
ForwardTo
29. Why do we use partitioned entities in Service Bus?
Partitioning spreads an entity across several message brokers and stores, which raises throughput and improves availability, because one failing partition does not take the whole entity down.
A message is placed in a partition based on PartitionKey, then SessionId, then MessageId. Ordering is therefore guaranteed only within a partition, so use a key when related messages must stay together.
The setting is fixed at creation time. In Premium, partitioning is configured when the namespace is created.
Partitioning also avoids a single hot broker, but it adds a constraint: you cannot rely on global ordering, so use a stable key when messages for one entity must stay together.
Take quiz
Across all partitions
Across the namespace
Within a single partition
Only for scheduled messages
Yes, with a portal toggle
Yes, by changing the SAS policy
Yes, but only in Basic
No, it is set at creation
30. When should you choose Premium over Standard tier?
Standard is multi-tenant, so latency and throughput can vary with neighbors. Premium gives you dedicated resources measured in messaging units (1, 2, 4, 8 or 16).
- Predictable latency and throughput for production-critical loads.
- Messages larger than 256 KB, up to 100 MB.
- Private endpoints, VNet rules and customer-managed keys.
- Geo-disaster recovery and availability zones.
- JMS 2.0 for Java applications.
The trade-off is cost: Premium bills per messaging unit per hour even if idle. Stay on Standard for dev/test and modest workloads.
A simple decision rule: if you need private networking, large messages, or a latency guarantee, choose Premium. Otherwise Standard is usually the better value.
Take quiz
Support for topics
Support for queues
Dead-letter queues
Private endpoints and 100 MB messages
By adding messaging units
By buying extra topics
By raising the lock duration
By increasing TTL
31. How do you implement request-reply with Service Bus?
The client sends a request to a queue and tells the service where to answer.
- Client creates a reply queue (or uses a session) and sets
ReplyToto it. - Client sets
MessageIdon the request. - Service processes it and replies to the
ReplyToentity, copying the request ID intoCorrelationId. - Client matches the reply by
CorrelationId.
With many clients sharing one reply queue, set ReplyToSessionId so each client receives only its own replies.
Set a TimeToLive on requests. If the service is down, stale requests expire instead of piling up and answering clients that already timed out.
sequenceDiagram Client->>RequestQueue: Request (MessageId=42, ReplyTo=replies) RequestQueue->>Service: Deliver Service->>Replies: Response (CorrelationId=42) Replies->>Client: Match by CorrelationId
Take quiz
CorrelationId
LockToken
SequenceNumber
PartitionKey
Longer TTL
ReplyToSessionId
Duplicate detection
Auto-forwarding
32. How can you send payloads larger than the message limit?
Standard allows 256 KB per message, including headers. Premium goes to 100 MB. If the payload is bigger, or you want to keep the broker lean, use the claim-check pattern.
- Upload the large payload to Blob Storage.
- Send a small Service Bus message containing the blob URI and metadata.
- The consumer reads the message, downloads the blob, then processes it.
Remember to clean up blobs after completion, for example with a lifecycle policy. Compressing JSON before sending is another cheap win for payloads just over the limit.
Also ensure the consumer can reach the storage account with a managed identity, and treat the blob and the message as one unit when handling failures.
Take quiz
Competing consumers
Claim check
Outbox
Scatter-gather
The DLQ
Session state
Blob Storage
Message subject
33. How can you secure access to a Service Bus namespace?
Layer identity, network and data protection.
- Identity - use Entra ID with managed identities and the Data Sender/Receiver roles. Disable SAS (local auth) if you do not need it.
- Least privilege - if SAS is required, use entity-level policies with only Send or Listen, never the root Manage key.
- Network - use private endpoints, VNet rules and IP firewall rules (Premium).
- Encryption - TLS in transit, encryption at rest, and customer-managed keys on Premium.
Rotate any SAS keys and keep them out of source control.
Review access regularly. Entra role assignments can be audited, while shared keys leave no per-identity trail.
Take quiz
Remove the dead-letter queue
Set lock duration to zero
Disable local authentication
Turn off duplicate detection
Basic only
Standard only
All tiers equally
Premium
34. What happens when the queue reaches its maximum size?
When an entity hits its size quota, new sends fail with a quota exceeded error. Existing messages are not lost, and receivers can still read and complete messages, which frees space.
Dead-lettered messages and scheduled messages count toward the size too, so a forgotten DLQ can fill a queue silently.
Fixes: scale out consumers, drain the DLQ, set a sensible TTL, raise the size limit, or use partitioning or Premium for more headroom. Senders should treat this error as a back-pressure signal and retry with back-off.
Monitor the Size metric and alert at around 80 percent, so you can react before senders start failing.
Take quiz
They silently overwrite old messages
They are queued on the client forever
They go to the DLQ
They fail with a quota exceeded error
Yes
No
Only in Basic
Only if they are older than a day
35. How does Azure Functions integrate with Service Bus?
A ServiceBusTrigger runs your function whenever messages arrive in a queue or subscription. The Functions runtime uses peek-lock: success completes the message, an unhandled exception abandons it.
Functions scale out automatically as the backlog grows, but remember the downstream limit. A flood of parallel executions can overwhelm a database, so cap concurrency in host.json. Poison messages end in the dead-letter queue, so add an alert there.
[Function("ProcessOrder")] public async Task Run( [ServiceBusTrigger("orders", Connection = "SbConn")] ServiceBusReceivedMessage msg, ServiceBusMessageActions actions) { await HandleAsync(msg.Body.ToString()); await actions.CompleteMessageAsync(msg); }
Tune maxConcurrentCalls and maxAutoLockRenewalDuration in host.json. For session queues set isSessionsEnabled. Repeated failures end in the DLQ once the delivery count is exhausted.
Take quiz
Abandoned and retried
Completed
Deleted
Moved to a different namespace
QueueTrigger
ServiceBusTrigger
EventHubTrigger
BlobTrigger
36. Why should consumers of Service Bus messages be idempotent?
Peek-lock gives at-least-once delivery. A lock can expire, a consumer can crash after doing work but before completing, or a sender can retry, so the same message can be processed twice.
An idempotent consumer produces the same result no matter how many times it sees a message. Techniques:
- Store processed
MessageIdvalues and skip repeats. - Use upserts or natural keys instead of blind inserts.
- Use conditional updates, e.g. with a version or ETag.
- Make external calls safe with idempotency keys.
Duplicate detection on the entity helps on the send side, but it does not remove the need for idempotent handlers.
Take quiz
Service Bus randomizes delivery
Delivery is at-least-once
Topics always duplicate to one subscription
SAS tokens expire
Raise MaxDeliveryCount to 1000
Use Receive-and-delete
Skip messages whose MessageId was already processed
Disable the DLQ
37. Explain the internal working of peek-lock message settlement?
When a receiver pulls a message in peek-lock mode, the broker does not delete it. It locks it for LockDuration, hides it from other receivers, increments DeliveryCount and hands over a LockToken.
The receiver then settles the message with one of four outcomes:
- Complete - the broker deletes it.
- Abandon - the lock is released and the message is immediately available again.
- Defer - it stays in the entity but is only retrievable by sequence number.
- Dead-letter - it moves to the DLQ with a reason.
If no settlement arrives before the lock expires, the broker behaves as if it was abandoned. Settlement must happen on the same link that received the message, so a dropped connection invalidates the lock token.
sequenceDiagram
Receiver->>Broker: Receive
Broker-->>Receiver: Message + LockToken (DeliveryCount+1)
alt Complete
Receiver->>Broker: Complete
Broker-->>Broker: Delete message
else Abandon or lock expired
Broker-->>Broker: Release, redeliver
else Dead-letter
Receiver->>Broker: DeadLetter(reason)
end
Take quiz
Deletes it immediately
Moves it to a deferred sub-queue
Locks it and increments DeliveryCount
Copies it to every subscription
The message TTL is reset
The DLQ becomes read-only
SAS rights are revoked
The lock token is tied to the receiving link
38. Explain the execution flow of session-enabled message processing?
With sessions, the unit of work is the session, not the message.
- The sender sets the same
SessionIdon related messages. ServiceBusSessionProcessorasks the broker to accept the next available session, which takes an exclusive session lock.- Messages in that session are handed to the handler one at a time, in order.
- The handler can read and write session state to remember progress.
- When the session is empty for
SessionIdleTimeout, the processor releases it and accepts another.
MaxConcurrentSessions controls how many sessions run in parallel, so throughput scales with the number of active sessions, not the number of messages.
flowchart TD
A["Sender: SessionId=order-7"] --> B["Queue with sessions"]
B --> C["Processor accepts session, takes lock"]
C --> D["Handle messages in order"]
D --> E{Session idle?}
E -- No --> D
E -- Yes --> F["Release lock, accept next session"]
Take quiz
A lock on the whole namespace
A copy of every message
A SAS token per message
An exclusive lock on the session
The number of active sessions processed concurrently
The size of each message body
The number of topics
The TTL value
39. How do you troubleshoot messages stuck in the active queue?
If ActiveMessages keeps growing, work through these causes.
- No working consumer - the processor stopped, crashed or lost its credentials. Check the app logs and the
OutgoingMessagesmetric. - Consumer too slow - compare incoming against completed messages and raise concurrency or add instances.
- Session locked - on session entities, an orphaned or very long session blocks its messages.
- Not yet visible - scheduled or deferred messages are counted separately and will not be delivered normally.
- Lock-expiry loop - slow handlers cause redelivery, check
DeliveryCountrising. - Wrong routing - a subscription rule sends messages to a different subscription.
Use Service Bus Explorer to peek messages without locking them, and check the dead-letter and throttling metrics next.
A quick triage order is: consumers alive, throughput versus incoming rate, session or lock problems, then filter routing.
Take quiz
Scheduled messages
Completed messages
Active unlocked messages
Messages in a free session
Receive them in receive-and-delete mode
Peek them with Service Bus Explorer
Dead-letter them first
Auto-forward them to a topic
40. How can you optimize Service Bus throughput?
Most gains come from the client side.
- Reuse one long-lived
ServiceBusClientand sender or receiver. Creating them per message is very costly. - Batch sends with
CreateMessageBatchAsyncto cut network round trips. - Raise concurrency - increase
MaxConcurrentCallsand run several consumer instances. - Use prefetch for receivers with fast handlers.
- Keep messages small and compress if needed.
- Scale the broker - add messaging units on Premium, or enable partitioning.
- Stay in the same region as the namespace to cut latency.
Measure first. Often the bottleneck is the downstream database or API, not Service Bus.
After each change, re-test with realistic message sizes and handler times. Prefetch and concurrency tuned for tiny messages often behave very differently under real load. Also avoid doing slow work such as large database writes inside the receive loop without enough concurrency.
Take quiz
Creating a new client per message
Sending messages in batches
Lowering lock duration
Disabling TTL
Reusing the sender
Using AMQP
Creating a new client for every message
Using async calls
41. How does Geo-Disaster Recovery work in Service Bus?
Geo-DR is a Premium feature. You pair a primary namespace in one region with a secondary in another and expose them under one alias hostname.
Only metadata is replicated: queues, topics, subscriptions, rules and settings. Messages themselves are not copied. Applications connect to the alias, never to the namespace directly.
On a regional outage you trigger a manual failover. The alias then points at the secondary, and the pairing is broken. Messages still in the primary stay there until it recovers, so plan for that gap in your RPO. Newer geo-replication options that also replicate data exist on Premium, so check the current docs for availability and modes.
flowchart LR App --> Alias["Alias FQDN"] Alias --> P["Primary namespace"] P -. metadata only .-> S["Secondary namespace"] Alias -. after failover .-> S
Take quiz
All messages and metadata
Only dead-lettered messages
Metadata, not messages
Only SAS keys
Directly to the primary namespace
Directly to the secondary namespace
Through a Storage account
Through the alias hostname
42. How do you design a retry strategy for Service Bus consumers?
Use two layers.
Client-level retries handle transient network or service errors. ServiceBusRetryOptions defaults to exponential mode, 3 retries, 0.8 s delay and a 60 s maximum delay.
Message-level retries handle business failures. Abandon the message so it is redelivered, up to MaxDeliveryCount, then it goes to the DLQ.
| Failure type | Action |
| Transient (timeout, 503) | Abandon, retry with back-off |
| Needs a delay | Complete and schedule a new copy later |
| Permanent (bad payload) | Dead-letter immediately with a reason |
Never retry permanent errors, since that only wastes the delivery budget.
Add a circuit breaker around a failing dependency, so consumers pause instead of burning every message's delivery attempts during an outage. Record the attempt number in logs for easier diagnosis. Keep retry delays well below the lock duration, or renew the lock while waiting.
Take quiz
Abandon it forever
Retry 1000 times
Defer it for a year
Dead-letter it with a reason
MaxDeliveryCount
LockDuration
ForwardTo
MaxConcurrentCalls
43. How do you troubleshoot Service Bus throttling (ServerBusy) errors?
Throttling shows up as ServerBusyException or an HTTP 429, and the SDK retries it with back-off. If it persists, find out whether you are hitting a limit.
- Check the ThrottledRequests metric and the CPU and memory usage of the namespace (Premium).
- Look for bursts from too many senders or very small, unbatched sends.
- Reduce the request rate with batching and back-off.
- On Premium, add messaging units or enable autoscale. On Standard, consider upgrading to Premium.
- Spread unrelated workloads across separate namespaces.
On Standard, throttling is also affected by other tenants, which is a key reason to move critical workloads to Premium.
If the cause is an unbatched burst, the fix is often client-side. A single batch send counts far less than hundreds of individual sends.
Take quiz
ThrottledRequests
ActiveMessages
ScheduledMessages
Size
Shorten the lock duration
Add messaging units
Disable the DLQ
Reduce the TTL to zero
44. Which is better and why: SAS or Microsoft Entra ID authentication?
For most production workloads, Entra ID is better.
| Aspect | SAS | Microsoft Entra ID |
| Secret to manage | Yes, keys and connection strings | None with managed identity |
| Granularity | Per policy, with 3 rights | Per role and scope (namespace, queue, subscription) |
| Auditing | Weak, shared key | Per-identity audit trail |
| Revocation | Rotate the key | Remove the role assignment |
SAS still helps for third parties without an Azure identity or for time-limited delegated access. Whichever you use, grant the least privilege and consider disabling local auth once all clients use Entra ID.
Migration tip: add the Entra role assignments first, switch clients over one at a time, verify traffic in metrics, and only then disable local auth. For service-to-service calls inside Azure, managed identities remove key rotation work entirely.
Take quiz
Higher message size limit
No shared secret, with per-identity auditing
Faster delivery
Free of charge
Authenticating managed identities
Replacing RBAC
Granting limited access to a third party without an Azure identity
Encrypting messages
45. Why do we use the transactional outbox pattern with Service Bus?
Saving to your database and publishing to Service Bus are two separate systems, so a crash between them leaves data saved but no message sent, or the reverse. Service Bus transactions cannot enlist your database.
With an outbox, you write the business change and an outbox row in the same database transaction. A background relay then reads unsent rows, publishes them and marks them sent.
Set the outbox row ID as MessageId so duplicate detection drops repeats if the relay crashes mid-way. Consumers should still be idempotent.
An alternative is Change Data Capture, which publishes from the database log. It removes the relay table, but ties you to the database's features.
flowchart LR A[API] -->|1. one DB transaction| B[(Business table + Outbox table)] C[Relay] -->|2. read unsent| B C -->|3. publish MessageId=outbox id| D["Service Bus"] C -->|4. mark sent| B
Take quiz
Compressing large payloads
Ordering messages across partitions
Atomically saving data and publishing a message
Encrypting the body
To set the lock duration
To pick the partition
To route to the DLQ
So duplicate detection can drop repeated publishes
46. What is the difference between prefetch and MaxConcurrentCalls?
They tune different things, so don't mix them up.
| Setting | Controls | Watch out for |
PrefetchCount |
How many messages the client fetches ahead into a local buffer | Prefetched messages are already locked, so slow handlers can let locks expire |
MaxConcurrentCalls |
How many handler invocations run in parallel | Downstream systems must tolerate the parallelism |
Prefetch cuts network latency and helps when handlers are fast. Concurrency increases processing parallelism. Start with a modest prefetch, raise concurrency to match what your dependencies can take, and watch for lock-lost errors.
Typical starting point: modest prefetch, concurrency sized to the downstream limit, then watch the lock-lost and abandoned message counts as you tune. Prefetch counts apply per receiver, so total buffered messages grow with the number of instances.
Take quiz
MaxConcurrentCalls
LockDuration
MaxDeliveryCount
PrefetchCount
Locks expiring while messages wait in the buffer
Messages being deleted
The DLQ filling instantly
Topics being unsubscribed
47. How do you monitor Service Bus with Azure Monitor?
Use platform metrics for health and diagnostic logs for detail.
| Metric | Alert when |
| ActiveMessages | Keeps growing, consumers are behind |
| DeadLetteredMessages | Above zero or rising |
| ThrottledRequests | Sustained non-zero |
| ServerErrors / UserErrors | Spike over baseline |
| CPU / memory (Premium) | Consistently high, add messaging units |
Send diagnostic logs such as operational and runtime audit logs to Log Analytics and query them with KQL. Set action-group alerts on the DLQ count, since nothing else tells you that messages are failing.
Use dashboards for trend views, and alerts for what needs action. A DLQ above zero, rising active messages and throttling are the three most useful alerts. Add a dashboard tile for each so the on-call engineer sees backlog and failure trends together in one view.
Take quiz
DeadLetteredMessages
Size only
Completed messages
Scheduled messages
Event Grid
Log Analytics
Storage Queues
Azure DNS
48. How can you implement priority queues with Service Bus?
Service Bus has no built-in message priority, so you build it with separate paths per priority.
Publish to a topic with a Priority property. Create subscriptions with correlation filters for high, normal and low. Give the high subscription more consumers, or poll it first.
Avoid starving the low tier by guaranteeing it a minimum number of consumers. An alternative is separate queues per priority, which is simpler if there is no fan-out.
This design is simple to monitor too: each priority has its own backlog metric, so you can alert on high-priority latency separately. Alert separately when the high-priority backlog age exceeds your target, since that is the SLA that matters.
flowchart LR P[Publisher] --> T[Topic] T -->|Priority=high| H["High sub: many consumers"] T -->|Priority=normal| N["Normal sub"] T -->|Priority=low| L["Low sub: few consumers"]
Take quiz
Yes, via a Priority property that reorders
No, you model it with separate subscriptions or queues
Yes, only in Premium
Yes, via sessions
Delete the low subscription
Raise its TTL to zero
Guarantee it a minimum number of consumers
Disable its filter
49. How does message ordering behave with competing consumers?
A queue hands messages out in order, but two consumers working in parallel can finish them in any order. Retries make it worse, because an abandoned message is redelivered after later ones may already be done.
If order matters you have three options:
- Sessions - one receiver owns a session, so its messages are handled sequentially. This is the standard answer.
- Single consumer with
MaxConcurrentCalls = 1, which limits scale. - Sequence checks in the consumer, using a business version number to discard or park out-of-order messages.
On partitioned entities, ordering is only guaranteed within a partition, so use a stable PartitionKey or SessionId.
In practice, many systems accept loose ordering and rely on idempotent handlers plus version numbers, using sessions only for the streams where strict order truly matters.
Take quiz
Prefetch
Duplicate detection
Sessions
Auto-forwarding
Retries delete earlier messages
The broker sorts by size
Retries move to the DLQ first
An abandoned message is redelivered after later ones may be done
50. How do you scale Service Bus consumers on Kubernetes with KEDA?
KEDA watches the backlog and scales your deployment, even down to zero. The azure-servicebus scaler reads the queue or subscription message count.
Set a graceful shutdown period longer than your handler time, so scale-down does not cut messages mid-processing and push them back through lock expiry. Also test scale-from-zero latency, since the first message waits for a pod to start.
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: orders-worker spec: scaleTargetRef: name: orders-worker minReplicaCount: 0 maxReplicaCount: 20 triggers: - type: azure-servicebus metadata: queueName: orders messageCount: "50" authenticationRef: name: sb-auth
Authenticate with workload identity through a TriggerAuthentication. Set messageCount to the backlog one replica can handle, and cap replicas to what downstream systems tolerate. With sessions, replicas beyond the number of active sessions sit idle.