Microsoft Azure Service Bus documentation
Azure Service Bus — Complete Guide with C#
1. What is Azure Service Bus?
Azure Service Bus is a cloud-based message broker.
Its primary job is to allow applications and services to communicate without directly calling each other.
Instead of:
Order Service
|
| HTTP call
v
Payment Service
we can use:
Order Service
|
| Message
v
Azure Service Bus
|
| Message
v
Payment Service
This creates loose coupling between services.
Azure Service Bus supports messaging features such as queues, topics/subscriptions, dead-lettering, duplicate detection, transactions, sessions and scheduled messages.
2. Why do we need Service Bus?
Suppose you have an e-commerce application:
Angular
|
v
Order API
|
+---- Payment Service
|
+---- Inventory Service
|
+---- Notification Service
The Order API directly calls all three services.
Imagine:
Payment Service → 5 seconds
Inventory Service → 2 seconds
Email Service → 3 seconds
The Order API could end up waiting for multiple downstream services.
There are also other problems:
Payment service may be unavailable.
Inventory service may be overloaded.
Email service may be temporarily down.
Network failures can occur.
Services become tightly coupled.
Instead:
Order API
|
|
v
Azure Service Bus
|
+-----------+-----------+
| | |
v v v
Payment Inventory Notification
Service Service Service
Now the services communicate asynchronously.
3. What exactly is a message?
A message is simply a piece of data sent from one component to another.
For example:
{
"OrderId": 1001,
"CustomerId": 5001,
"Amount": 2500.00
}
We can send that message to Service Bus.
The message could represent:
OrderCreated
PaymentRequested
InventoryReserved
EmailRequested
InvoiceGenerated
4. The most important Service Bus concepts
You need to understand:
Service Bus Namespace
|
+---- Queue
|
+---- Topic
|
+---- Subscription
+---- Subscription
Let's understand each.
5. Service Bus Namespace
A namespace is the container for your Service Bus messaging resources.
Think of it like:
Azure
|
+-- Service Bus Namespace
|
+-- orders queue
+-- payments queue
+-- order-events topic
Your application connects to the namespace and accesses queues/topics inside it.
6. Queue
A queue is used for one message → one consumer/processing operation.
Architecture:
Producer
|
v
+-------------------+
| Orders Queue |
+-------------------+
|
v
Consumer
Example:
Order API
|
v
Orders Queue
|
v
Order Processing Service
The producer doesn't have to wait for the consumer.
7. How a Queue Actually Works
Let's take:
Order API
Customer creates:
Order #1001
The API creates:
{
"OrderId": 1001,
"CustomerId": 50,
"Amount": 5000
}
It sends this message to:
orders
Now:
Order API
|
| Message
v
+--------------------+
| orders queue |
| |
| Message #1001 |
+--------------------+
The message stays in the queue until a consumer receives/processes it.
Then:
Orders Queue
|
v
Order Processor
8. Important Concept: Producer and Consumer
Producer
The application that sends the message.
Order API
Consumer
The application that receives/processes the message.
Order Processing Service
So:
Producer
|
v
Service Bus
|
v
Consumer
9. Real-Time Example
Imagine Amazon-style order processing.
Customer clicks:
BUY NOW
Angular:
POST /api/orders
ASP.NET Core:
OrderController
|
v
OrderService
|
+---- Save order
|
+---- Send OrderCreated message
|
v
Azure Service Bus
|
v
Order Processor
|
+------+------+
| |
v v
Inventory Payment
This is a classic real-world use case.
10. Install the C# NuGet Package
For .NET:
dotnet add package Azure.Messaging.ServiceBus
Microsoft's current .NET SDK for Service Bus is Azure.Messaging.ServiceBus.
11. Sending a Message — C#
Suppose we have:
public class OrderCreatedEvent
{
public int OrderId { get; set; }
public int CustomerId { get; set; }
public decimal Amount { get; set; }
}
Now create the sender.
using Azure.Messaging.ServiceBus;
using System.Text.Json;
public class OrderMessagePublisher
{
private readonly ServiceBusSender _sender;
public OrderMessagePublisher(ServiceBusClient client)
{
_sender = client.CreateSender("orders");
}
public async Task PublishAsync(OrderCreatedEvent order)
{
var json = JsonSerializer.Serialize(order);
var message = new ServiceBusMessage(json);
await _sender.SendMessageAsync(message);
}
}
12. Register Service Bus in ASP.NET Core
In Program.cs:
using Azure.Messaging.ServiceBus;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ServiceBusClient>(sp =>
{
var configuration =
sp.GetRequiredService<IConfiguration>();
var connectionString =
configuration["ServiceBus:ConnectionString"];
return new ServiceBusClient(connectionString);
});
builder.Services.AddScoped<OrderMessagePublisher>();
var app = builder.Build();
app.Run();
Configuration:
{
"ServiceBus": {
"ConnectionString": "YOUR_CONNECTION_STRING"
}
}
Don't put real production secrets in source control.
In production, prefer Managed Identity + Azure RBAC, with secrets/certificates handled through appropriate Azure security services.
13. Controller Sends Message
[ApiController]
[Route("api/orders")]
public class OrdersController : ControllerBase
{
private readonly OrderMessagePublisher _publisher;
public OrdersController(
OrderMessagePublisher publisher)
{
_publisher = publisher;
}
[HttpPost]
public async Task<IActionResult> CreateOrder(
OrderCreatedEvent order)
{
// Save order to database first
await _publisher.PublishAsync(order);
return Accepted(new
{
Message = "Order accepted",
order.OrderId
});
}
}
Notice:
return Accepted();
HTTP 202 Accepted is often appropriate when the request has been accepted for asynchronous processing but the downstream work is not necessarily complete yet.
14. Receiving the Message
Now let's create the consumer.
There are several ways to consume Service Bus messages. In a .NET worker or ASP.NET Core application, the ServiceBusProcessor is a common approach.
using Azure.Messaging.ServiceBus;
using System.Text.Json;
public class OrderMessageConsumer
{
private readonly ServiceBusProcessor _processor;
public OrderMessageConsumer(ServiceBusClient client)
{
_processor =
client.CreateProcessor("orders");
}
public async Task StartAsync()
{
_processor.ProcessMessageAsync += ProcessMessage;
_processor.ProcessErrorAsync += ProcessError;
await _processor.StartProcessingAsync();
}
private async Task ProcessMessage(
ProcessMessageEventArgs args)
{
var order =
JsonSerializer.Deserialize<OrderCreatedEvent>(
args.Message.Body.ToString());
if (order == null)
return;
Console.WriteLine(
$"Processing Order {order.OrderId}");
// Business logic
await args.CompleteMessageAsync(
args.Message);
}
private Task ProcessError(
ProcessErrorEventArgs args)
{
Console.WriteLine(args.Exception);
return Task.CompletedTask;
}
}
15. What happens internally?
Let's visualize it:
Producer
|
|
| SendMessageAsync()
v
+-------------------+
| |
| Service Bus |
| |
| Orders Queue |
| |
| Message #1001 |
| |
+-------------------+
|
|
| Receive
v
Consumer
|
v
Process Order
|
v
CompleteMessageAsync()
That last step is very important.
16. Complete Message
When processing succeeds:
await args.CompleteMessageAsync(args.Message);
This tells Service Bus:
"The consumer successfully processed this message."
The message is then removed from the queue.
17. What if Processing Fails?
Suppose:
Order #1001
|
v
Consumer
|
v
SQL Database
|
X
Database unavailable
If processing fails and the message isn't completed, Service Bus can make the message available again according to its delivery/lock behavior.
Conceptually:
Message
|
Consumer
|
Failure
|
Retry
|
Failure
|
Retry
|
Failure
|
Dead Letter Queue
This is one of the most important concepts to understand.
18. Dead Letter Queue — DLQ
A Dead Letter Queue is a special subqueue for messages that can't be successfully processed.
Example:
Orders Queue
|
v
Function
|
X
Processing failed
|
v
Retry
|
X
Retry
|
X
Retry exhausted
|
v
Dead Letter Queue
Operations teams can inspect the DLQ and determine why the message failed.
Service Bus provides dead-lettering as part of its messaging capabilities.
19. Why is DLQ important?
Imagine you receive:
{
"OrderId": 1001,
"Amount": -500
}
This is invalid.
If you continually retry it:
Retry
Retry
Retry
Retry
Retry
...
you are wasting resources.
Instead:
Invalid Message
|
v
Dead Letter Queue
Then the team can inspect it.
20. Queue vs Topic
This is one of the most important interview questions.
Queue
One message is normally processed by one competing consumer.
Producer
|
v
Queue
|
+---- Consumer 1
|
+---- Consumer 2
Multiple consumers can compete for messages.
Topic
A topic is useful for publish/subscribe.
Producer
|
v
OrderCreated
Topic
|
+------------+------------+
| | |
v v v
Subscription Subscription Subscription
| | |
v v v
Payment Inventory Notification
Each subscription can receive its own copy of the event.
21. Real-Time Topic Example
Suppose:
OrderCreated
Three systems need to know about it:
Payment
Inventory
Email
Don't create:
Order API
|
+---- Payment
+---- Inventory
+---- Email
Instead:
Order API
|
v
Service Bus Topic
|
+---- Payment Subscription
|
+---- Inventory Subscription
|
+---- Notification Subscription
Now each service receives the event independently.
This is publish/subscribe.
22. Queue vs Topic — Interview Answer
| Queue | Topic |
|---|---|
| Point-to-point messaging | Publish/subscribe |
| One processing path per message | Multiple subscriptions can receive event |
| Good for work distribution | Good for broadcasting events |
| Consumers compete for messages | Each subscription gets its own message stream |
Interview answer:
"I use a queue when one processing operation needs to consume a message. I use a topic when multiple independent services need to react to the same event."
23. How Services Communicate Through Service Bus
Let's take:
Order Service
Payment Service
Inventory Service
Notification Service
Instead of direct HTTP calls:
Order
|
+----HTTP----> Payment
|
+----HTTP----> Inventory
|
+----HTTP----> Notification
we use:
Order Service
|
v
Service Bus Topic
|
+--------------+--------------+
| | |
v v v
Payment Inventory Notification
Subscription Subscription Subscription
This creates loose coupling.
24. What does Loose Coupling mean?
Without Service Bus:
Order Service
|
| needs Payment API
v
Payment Service
Order service knows:
Payment service URL
Payment API contract
Payment availability
Network connection
With Service Bus:
Order Service
|
v
Service Bus
The Order Service only needs to know:
"I need to publish an OrderCreated event."
It doesn't need to know which consumers are listening.
That's loose coupling.
25. Synchronous vs Asynchronous Communication
Synchronous
Order API
|
| HTTP
v
Payment
|
| Response
v
Order API
The caller waits.
Asynchronous
Order API
|
| Message
v
Service Bus
|
v
Return response
Later:
Service Bus
|
v
Payment Service
The producer doesn't need to wait for the consumer to finish processing.
26. When Should You Use Synchronous Communication?
Use HTTP/API calls when the caller immediately needs a response.
Example:
GET /api/products/100
You need:
{
"id": 100,
"name": "Laptop"
}
That's naturally synchronous.
27. When Should You Use Service Bus?
Good examples:
Order processing
Payment processing
Email notification
Report generation
File processing
Background jobs
Integration between microservices
Long-running processing
Traffic spike absorption
28. Important: Service Bus Does NOT Replace HTTP
A common beginner mistake is:
"We have Service Bus, so we don't need REST APIs."
Wrong.
Use:
HTTP
for:
Request → Immediate Response
Use:
Service Bus
for:
Message → Asynchronous Processing
A real application often uses both.
29. Real Enterprise Architecture
Here's a strong architecture for an interview:
Angular
|
v
Azure API Management
|
v
ASP.NET Core API
|
+------+------+
| |
v v
Azure SQL Service Bus
|
OrderCreated Topic
|
+------------------+----------------+
| | |
v v v
Payment Inventory Notification
Service Service Service
| | |
v v v
Payment DB Inventory DB Email Provider
This is a classic event-driven microservices architecture.
30. C# Event Model
Instead of sending random strings, create event contracts.
public record OrderCreatedEvent(
Guid EventId,
int OrderId,
int CustomerId,
decimal Amount,
DateTime CreatedAt);
Then:
var orderEvent = new OrderCreatedEvent(
Guid.NewGuid(),
order.Id,
order.CustomerId,
order.TotalAmount,
DateTime.UtcNow);
Serialize:
var json =
JsonSerializer.Serialize(orderEvent);
var message =
new ServiceBusMessage(json);
31. Message Metadata
A Service Bus message isn't only a body.
You can attach metadata.
Example:
var message = new ServiceBusMessage(json)
{
MessageId = orderEvent.EventId.ToString(),
Subject = "OrderCreated",
CorrelationId = order.Id.ToString(),
ContentType = "application/json"
};
This is useful for tracing and troubleshooting.
32. MessageId
Suppose:
MessageId = ABC123
If the same message arrives again:
ABC123
your consumer can use this ID to implement idempotency.
33. CorrelationId
This is extremely useful in microservices.
Imagine:
API Request
CorrelationId = 12345
Then:
Order API
|
| CorrelationId 12345
v
Service Bus
|
v
Payment
|
v
Inventory
|
v
Notification
Now you can search logs for:
CorrelationId = 12345
and follow the entire transaction.
For a Lead, distributed tracing/correlation is an important production topic.
34. Message Lock
When a consumer receives a message, Service Bus can lock that message temporarily so another consumer doesn't process it simultaneously.
Conceptually:
Queue
|
v
Consumer A
|
Lock acquired
|
Processing
If processing completes:
Complete
If processing doesn't complete successfully before the lock expires, the message can become available again.
This is one reason long-running processing needs careful design.
35. At-Least-Once Processing
In distributed messaging systems, you should design consumers expecting that a message may be delivered more than once.
Example:
Message
|
Consumer
|
Process payment
|
Network failure
|
Consumer doesn't successfully complete message
|
Message becomes available again
Now:
Same message
|
v
Consumer again
Therefore:
Consumers should be idempotent.
This is a very important Lead-level concept.
36. Idempotency Example
Suppose:
OrderId = 1001
We maintain:
ProcessedMessages
-------------------------
MessageId
ProcessedAt
Before processing:
var exists =
await db.ProcessedMessages
.AnyAsync(x => x.MessageId == messageId);
if (exists)
{
return;
}
Then:
Message
|
Already processed?
/ \
Yes No
| |
Stop Process
|
v
Record MessageId
37. Important Production Problem: Database + Service Bus
Imagine:
API
|
+---- Save Order to SQL
|
+---- Send Service Bus Message
What happens if:
SQL Save → SUCCESS
Service Bus → FAILURE
Now your database says:
Order Created
but your message wasn't published.
This is called a dual-write consistency problem.
38. Outbox Pattern
For a Lead interview, this is a fantastic concept.
Instead of:
SQL
|
+---- Order
|
+---- Service Bus
we save both the order and an event/outbox record in the same database transaction:
SQL Transaction
|
+---- Order
|
+---- Outbox Event
Then a background publisher:
Outbox
|
v
Service Bus
Architecture:
API
|
v
SQL Transaction
/ \
/ \
v v
Orders OutboxEvents
|
v
Outbox Publisher
|
v
Service Bus
|
+----------+----------+
| |
v v
Payment Inventory
This helps ensure that the database change and event publication are not accidentally separated.
39. Retry Strategy
Suppose Service Bus consumer calls SQL:
Function
|
v
Azure SQL
|
X
Temporary failure
You might retry:
Attempt 1
↓
wait
Attempt 2
↓
wait
Attempt 3
Use exponential backoff where appropriate.
For example:
1 second
2 seconds
4 seconds
8 seconds
Don't retry permanent errors indefinitely.
For example:
400 Bad Request
Invalid message
Invalid business rule
usually shouldn't be blindly retried.
40. Poison Messages
A poison message is a message that repeatedly causes processing failures.
Example:
{
"OrderId": -1,
"Amount": -5000
}
Consumer:
Message
|
Validation
|
FAIL
|
Retry
|
FAIL
|
Retry
|
FAIL
|
DLQ
Then support staff can investigate.
41. Service Bus + Azure Function
This is an extremely common architecture:
ASP.NET Core API
|
v
Service Bus
|
v
Azure Function
|
v
Process Order
Function:
[Function("ProcessOrder")]
public async Task Run(
[ServiceBusTrigger(
"orders",
Connection = "ServiceBusConnection")]
string message)
{
var order =
JsonSerializer.Deserialize<OrderCreatedEvent>(
message);
await _orderService.ProcessAsync(order!);
}
This is a very common Azure/.NET combination.
42. Service Bus + Multiple Services
Suppose one event:
OrderCreated
needs three consumers.
Use a topic:
Order API
|
v
OrderCreated Topic
|
+------------+-------------+
| | |
v v v
Payment Sub Inventory Sub Email Sub
| | |
v v v
Payment Service Inventory Notification
Each subscription can independently process the event.
43. How do services communicate?
This is probably the most important part of your question.
They don't necessarily communicate directly.
Instead:
Service A
Publishes:
OrderCreated
to:
Service Bus Topic
Service B
subscribes:
PaymentSubscription
Service C
subscribes:
InventorySubscription
Service D
subscribes:
NotificationSubscription
So:
Event
|
v
Service Bus
|
+------------+------------+
| | |
v v v
Payment Inventory Notification
That is event-driven communication.
44. Request/Response vs Event-Based Communication
You should know both.
Request/Response
Order Service
|
| HTTP Request
v
Payment Service
|
| HTTP Response
v
Order Service
The caller expects an immediate answer.
Event-Based
Order Service
|
| OrderCreated
v
Service Bus
|
+---- Payment
+---- Inventory
+---- Notification
The producer announces:
"An order has been created."
Consumers decide what to do.
45. When should you NOT use Service Bus?
This is also important in interviews.
Don't introduce messaging unnecessarily.
For example:
GET /api/products/100
You don't need:
API → Service Bus → Product Service
A synchronous API call is more appropriate.
Service Bus makes sense when you need:
Asynchronous processing
Decoupling
Work queues
Event distribution
Resilience against temporary downstream failures
Traffic buffering
46. Service Bus vs RabbitMQ
You might get this question.
Azure Service Bus
Best when you're heavily invested in Azure and want a managed Azure messaging platform.
RabbitMQ
An open-source message broker that can be self-managed or hosted through various providers.
For an Azure-native enterprise application:
ASP.NET Core
|
v
Azure Service Bus
is often an attractive choice because of Azure integration and managed operations.
47. Service Bus vs Storage Queue
| Service Bus | Storage Queue |
|---|---|
| Enterprise messaging | Simpler queue |
| Topics/subscriptions | Queue-focused |
| Rich messaging features | Simpler model |
| Sessions | No equivalent feature set |
| Dead lettering | Different capabilities |
| Duplicate detection | Richer messaging support |
| Transactions | More advanced messaging scenarios |
Interview answer
"If I need simple asynchronous work distribution, Storage Queue may be sufficient. If I need enterprise messaging features, topics/subscriptions, advanced delivery handling and richer messaging semantics, I would consider Service Bus."
48. Lead-Level Architecture
A strong .NET Lead architecture might look like:
CLIENT
|
v
Azure API Management
|
v
ASP.NET Core APIs
|
+----------+----------+
| |
v v
Azure SQL Service Bus
|
OrderCreated Topic
|
+---------------------+--------------------+
| | |
v v v
Payment Service Inventory Service Notification
| | |
v v v
Payment DB Inventory DB Email/SMS
+----------------+
| |
v v
Key Vault App Insights
|
v
Azure Monitor
49. What Would I Say in a Lead Interview?
If the interviewer asks:
"How do you use Azure Service Bus in your architecture?"
A strong answer would be:
"I use Azure Service Bus primarily for asynchronous communication and decoupling between services. For point-to-point workloads, I use queues. When multiple services need to react to the same business event, I use topics and subscriptions. For example, after an OrderCreated event, Payment, Inventory and Notification services can independently consume the event. I design consumers to be idempotent, use retries for transient failures, dead-letter poison messages, and use correlation IDs for distributed tracing. For database-plus-message consistency, I would consider the Outbox Pattern."
That is a very strong Lead-level answer.
50. Top Azure Service Bus Interview Questions
Beginner
What is Azure Service Bus?
What is a message broker?
What is a Service Bus namespace?
What is a queue?
What is a topic?
What is a subscription?
What is a producer?
What is a consumer?
What is a message?
What is a trigger?
Intermediate
Queue vs Topic?
Service Bus vs Storage Queue?
Synchronous vs asynchronous communication?
What is dead-lettering?
What is message lock?
What is message completion?
What is message abandonment?
What is duplicate detection?
What is message ordering?
What are competing consumers?
Advanced
How do you make a consumer idempotent?
How do you handle poison messages?
How do you implement retries?
How do you handle Service Bus downtime?
How do you prevent duplicate payment?
How do you maintain database/message consistency?
What is the Outbox Pattern?
How do you monitor Service Bus?
How do you scale consumers?
How do you control consumer concurrency?
Lead/Architect
Design an event-driven e-commerce system.
When would you choose Service Bus over REST?
When would you NOT use Service Bus?
Queue vs Topic in microservices?
How would you guarantee business-level idempotency?
How do you handle ordering requirements?
How would you handle 1 million messages?
How would you handle a slow consumer?
How would you prevent SQL from being overwhelmed?
How would you design disaster recovery?
How would you secure Service Bus?
Managed Identity vs connection string?
How would you trace one transaction across five services?
How would you handle schema evolution?
How would you handle backward compatibility of events?
51. The Most Important Architecture to Remember
If you remember only one diagram, remember this:
Angular
|
v
API Management
|
v
Order API
|
Save Order
|
v
OrderCreated Event
|
v
Azure Service Bus
|
Topic
|
+---------------+---------------+
| | |
v v v
Payment Inventory Notification
Subscription Subscription Subscription
| | |
v v v
Payment Service Inventory Email Service
|
v
Databases
And remember these five words:
Queue → Topic → Subscription → Retry → DLQ
For a .NET Lead interview, add these five:
Idempotency → Outbox → Correlation → Scaling → Observability
Together, these concepts cover a large portion of the Azure Service Bus questions you'll encounter in real-world .NET microservices interviews.
No comments:
Post a Comment