Choose a Service Bus queue when workers share one logical work stream; choose a topic with subscriptions when independent consumers each need their own copy. Then design settlement, ordering and recovery separately. Choosing a topic does not remove duplicate processing risk, and choosing a queue does not make concurrent business effects globally ordered.
Key takeaways
- Competing workers and independent subscribers solve different problems.
- Define ordering around the business entity that needs it.
- Consumer retries require idempotent or otherwise safely coordinated effects.
- A dead-letter queue needs an owner and a controlled repair process.
Queue vs topic: the consumer contract
Microsoft’s entity guide distinguishes point-to-point queues from durable publish/subscribe topics. A topic’s subscriptions provide separate consumption paths, with filters for selective delivery. Multiple workers can compete within one queue or one subscription.
ONE LOGICAL WORK STREAM
Producer → Queue → competing worker A / worker B
↓
one accepted business effect
INDEPENDENT CONSUMERS
Producer → Topic → Billing subscription → billing workers
→ Fulfillment subscription → fulfillment workers
→ Analytics subscription → analytics workersFor example, several invoice-rendering workers can share a queue when each render request should be handled once logically. If billing, fulfillment and analytics each need an order event, they need independent delivery obligations. Putting all three on one queue can cause one function to consume work another function required.
| Requirement | Starting design | Question to settle |
|---|---|---|
| Distribute tasks among equivalent workers | Queue | How are retries and duplicate effects handled? |
| Several independent consumers need the event | Topic with separate subscriptions | Who owns each subscription and its lag? |
| Only some events matter to a consumer | Reviewed subscription filter | Can a filter error silently exclude needed events? |
| Related messages require ordered handling | Session-aware design where supported | What is the ordering key and recovery policy? |
Version the event contract and subscription configuration. A new subscriber should not assume it automatically receives all historical business events. Define its onboarding, initialization and replay requirements explicitly.
Settlement and business effects
The entity guide describes receive-and-delete and peek-lock receiving. With peek-lock, processing and completion are separate steps. A failure between the business write and message completion can lead to redelivery, so the consumer must handle repeated delivery safely.
Use a stable business operation identifier and store evidence of accepted processing where appropriate. An “already processed” decision should follow the business contract, not a fragile in-memory flag that disappears when the worker restarts.
Receive locked message
→ validate contract and authorization context
→ apply effect with an approved idempotency strategy
→ record accepted outcome
→ complete message
Failure after effect but before completion?
→ replay must not repeat the business effectFor an external payment, email or partner API, define the destination’s idempotency behavior and reconciliation path. A database transaction inside the consumer does not automatically include a remote side effect. Keep retry policies bounded and distinguish transient infrastructure errors from invalid business messages.
Also handle producer uncertainty. If a sender times out, it may not know whether the message was accepted. Define stable identifiers and a supported retry strategy rather than generating a new business operation for every network retry.
Ordering, sessions and parallel work
Service Bus session documentation describes ordered processing of related messages through a session identifier and session-aware receivers. It also documents tier support and exclusive session locks. Verify these requirements before creating entities and clients.
Choose the smallest meaningful ordering scope. Order changes for one account may need a shared account key, while unrelated accounts can progress independently. Putting every message into one session can serialize the whole workload and create a bottleneck.
Broker arrival order and business causality are not identical. Two producers can emit updates in a different order from the underlying business events. Include a domain version or sequence where needed, then define how the consumer handles an obsolete, missing or unexpected version.
Do not let a handler launch uncontrolled parallel work inside an ordered sequence if completion order matters. Document what happens when the next message is invalid: pause the business stream, quarantine it with an explicit gap or follow another approved policy. Skipping a failed state transition can make later transitions meaningless.
Dead-letter queues require an operating process
Microsoft’s DLQ guide describes dead-letter subqueues for queues and subscriptions. They hold undeliverable or unprocessable messages and do not clean themselves up automatically. Inspect the reason and context before deciding on correction or resubmission.
- Identify the entity, affected business key and reason.
- Determine whether the cause is data, code, configuration or a failed dependency.
- Contain repeated failures and preserve necessary evidence.
- Correct the cause and test a small representative replay.
- Resubmit under an approved identity and idempotency policy.
- Verify the accepted business outcome before completing the recovery record.
Do not blindly replay the entire DLQ into the same broken consumer. That can create a loop, overload a dependency or repeat an already-applied effect. Keep repair permissions limited and record the operator, scope and result.
Define data retention and access for dead-letter payloads. Error descriptions and message bodies can contain confidential information. Alert channels should carry routing context rather than unrestricted copies of sensitive records.
Scaling with correctness intact
Observe arrival rate, successful completion rate, backlog age, lock losses, failures and dependency saturation. Queue depth alone is insufficient: a few old messages may be more serious than a large, quickly draining burst.
Increase concurrency only when downstream capacity and ordering rules allow it. More workers can increase database contention or trigger a partner’s throttling. For session workloads, inspect key distribution; one dominant session can remain the bottleneck despite spare workers.
Test batch sizes, prefetch and lock-renewal behavior using the actual SDK and processing duration. A configuration that improves throughput for quick messages can fail when handlers take longer. Confirm what happens under worker pauses and dependency timeouts.
For topics, observe each subscription independently. Billing can be healthy while fulfillment is delayed. Track each consumer’s obligation and recovery owner rather than reporting only that the topic accepted messages.
Recovery exercises before production
| Exercise | Expected evidence |
|---|---|
| Crash after business write, before completion | Redelivery does not duplicate the accepted effect |
| Slow handler or lost lock | Controlled retry and a reconciled outcome |
| Invalid contract version | Actionable rejection or quarantine path |
| Failed subscription consumer | Other obligations remain understood; affected lag is visible |
| Hot session key | Measured ordering/throughput trade-off |
| DLQ repair and replay | Cause fixed, scope recorded, output reconciled |
| Changed subscription filter | Fixture proves included and excluded event classes |
These are proposed exercises, not measured results from a deployed system. Use synthetic data and controlled failure injection, then retain run identifiers, expected effects and observed outcomes.
Before release, assign entity owners, contract owners, alert routes and replay authority. Review access to send, receive and administer separately. Apply the environment boundaries from the landing-zone checklist and correlate message processing with the observability runbook.
Common questions
What is the difference between queues and topics in Azure Service Bus?
A queue distributes one logical work stream among competing consumers. A topic uses subscriptions so independent consumers can each receive the events relevant to them.
Does a queue guarantee business effects finish in order?
Not simply by choosing a queue. Define the ordering scope, session and handler behavior, plus the response to failed or missing transitions.
Can a message be processed again after a worker failure?
Yes. Design repeated delivery and settlement uncertainty into the consumer’s idempotency and reconciliation strategy.
Should dead-letter messages be replayed automatically?
Only under an explicit, tested policy. Diagnose and fix the cause, then verify replay cannot repeat unsafe effects.
Why does adding workers sometimes fail to improve throughput?
A hot ordering key, downstream limits, lock behavior or resource contention can remain the bottleneck. Measure those constraints before increasing concurrency.
Design messaging around accepted business outcomes
Bring your consumer obligations, ordering keys and failure scenarios to a review. Discuss a cloud architecture and cost review to define messaging boundaries and a testable recovery plan.
