Service Bus Sending Messages

Sending messages to Azure Service Bus involves creating a client connection, building the message, and using a sender object to deliver it to a queue or topic. This topic covers message sending using the official .NET SDK, Python SDK, and Azure CLI, along with batch sending and error handling patterns.

How Sending Works — Overview

[Producer App]
    |
    | 1. Create ServiceBusClient (connection string)
    | 2. Create ServiceBusSender (target queue or topic)
    | 3. Build ServiceBusMessage (body + properties)
    | 4. Call SendMessageAsync()
    |
    v
[Azure Service Bus Queue / Topic]
    (Message stored safely until receiver picks it up)

Sending a Message — .NET SDK

Install the NuGet Package

dotnet add package Azure.Messaging.ServiceBus

Send a Single Message to a Queue

using Azure.Messaging.ServiceBus;

string connectionString = "Endpoint=sb://myshopns.servicebus.windows.net/;...";
string queueName = "orders";

await using var client = new ServiceBusClient(connectionString);
await using var sender = client.CreateSender(queueName);

var order = new
{
    orderId = 101,
    customerId = "C456",
    product = "Laptop",
    amount = 1200.00
};

string json = System.Text.Json.JsonSerializer.Serialize(order);

var message = new ServiceBusMessage(BinaryData.FromString(json))
{
    MessageId   = "order-101",
    Subject     = "NewOrder",
    ContentType = "application/json"
};

message.ApplicationProperties["Region"]   = "India";
message.ApplicationProperties["Priority"] = "High";

await sender.SendMessageAsync(message);
Console.WriteLine("Message sent successfully.");

Send a Single Message to a Topic

string topicName = "order-events";

await using var sender = client.CreateSender(topicName);

var message = new ServiceBusMessage(BinaryData.FromString(json))
{
    MessageId = "event-101",
    Subject   = "OrderPlaced"
};

await sender.SendMessageAsync(message);
Console.WriteLine("Event published to topic.");

Sending Batch Messages — .NET SDK

Sending messages one at a time creates many network round trips. Batch sending groups multiple messages into one operation, which improves throughput and reduces network cost.

await using var sender = client.CreateSender("orders");

// Create a batch
using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();

for (int i = 1; i <= 5; i++)
{
    var msg = new ServiceBusMessage($"Order {i}");

    if (!messageBatch.TryAddMessage(msg))
    {
        // Batch is full — send what we have and create a new batch
        await sender.SendMessagesAsync(messageBatch);
        Console.WriteLine($"Batch sent. Starting new batch from message {i}.");
        messageBatch.Dispose();
        messageBatch = await sender.CreateMessageBatchAsync();
        messageBatch.TryAddMessage(msg);
    }
}

// Send the last remaining batch
await sender.SendMessagesAsync(messageBatch);
Console.WriteLine("All batches sent.");

Batch Sending — How It Works

Batch 1:
  [msg1][msg2][msg3][msg4] --> sent in ONE network call

Batch 2:
  [msg5][msg6][msg7]       --> sent in ONE network call

Total: 7 messages sent in 2 network calls (instead of 7 calls)

Sending Messages — Python SDK

Install the Package

pip install azure-servicebus

Send a Single Message

from azure.servicebus import ServiceBusClient, ServiceBusMessage
import json

connection_str = "Endpoint=sb://myshopns.servicebus.windows.net/;..."
queue_name = "orders"

order = {
    "orderId": 101,
    "product": "Laptop",
    "amount": 1200.00
}

with ServiceBusClient.from_connection_string(connection_str) as client:
    with client.get_queue_sender(queue_name) as sender:
        msg = ServiceBusMessage(
            body=json.dumps(order),
            message_id="order-101",
            subject="NewOrder",
            content_type="application/json"
        )
        msg.application_properties = {
            "Region": "India",
            "Priority": "High"
        }
        sender.send_messages(msg)
        print("Message sent.")

Send Batch Messages — Python

with ServiceBusClient.from_connection_string(connection_str) as client:
    with client.get_queue_sender(queue_name) as sender:
        batch = sender.create_message_batch()

        for i in range(1, 6):
            try:
                batch.add_message(ServiceBusMessage(f"Order {i}"))
            except ValueError:
                # Batch is full — send and create a new one
                sender.send_messages(batch)
                batch = sender.create_message_batch()
                batch.add_message(ServiceBusMessage(f"Order {i}"))

        sender.send_messages(batch)
        print("Batch sent.")

Sending Messages — Azure CLI

# Send a test message to a queue using CLI (useful for quick testing)
az servicebus queue message send \
  --resource-group rg-messaging-prod \
  --namespace-name myshopns \
  --queue-name orders \
  --message-body "{ \"orderId\": 101 }"

Sending with Managed Identity (Recommended for Production)

Instead of using a connection string (which contains a secret key), production applications should use Managed Identity with role-based access control. This eliminates the risk of exposing connection string secrets.

using Azure.Identity;
using Azure.Messaging.ServiceBus;

string namespaceFqdn = "myshopns.servicebus.windows.net";
string queueName = "orders";

// Uses the app's Managed Identity automatically
var client = new ServiceBusClient(namespaceFqdn, new DefaultAzureCredential());
var sender = client.CreateSender(queueName);

var message = new ServiceBusMessage("Order payload here");
await sender.SendMessageAsync(message);

Message Send Options

OptionMethodWhen to Use
Single MessageSendMessageAsync(message)Low volume, individual transactions
Batch MessagesSendMessagesAsync(batch)High volume, bulk imports
Scheduled MessageSet ScheduledEnqueueTimeDelayed or future delivery
Send via TransactionCreateTransaction()Atomic multi-queue operations

Error Handling During Send

try
{
    await sender.SendMessageAsync(message);
    Console.WriteLine("Message sent.");
}
catch (ServiceBusException ex) when (ex.Reason == ServiceBusFailureReason.MessagingEntityNotFound)
{
    Console.WriteLine($"Queue not found: {ex.Message}");
}
catch (ServiceBusException ex) when (ex.Reason == ServiceBusFailureReason.QuotaExceeded)
{
    Console.WriteLine("Queue is full. Increase queue size or speed up consumption.");
}
catch (ServiceBusException ex) when (ex.IsTransient)
{
    // Transient errors are safe to retry
    Console.WriteLine("Transient error — retry the send operation.");
}
catch (ServiceBusException ex)
{
    Console.WriteLine($"Messaging error: {ex.Message}");
}

Common Send Errors

Error ReasonCauseAction
MessagingEntityNotFoundQueue or topic does not existCheck the name and namespace
QuotaExceededQueue or namespace has reached storage limitIncrease size limit or add consumers
UnauthorizedInvalid connection string or insufficient permissionsVerify access policy or RBAC role
MessageSizeExceededMessage body is larger than the tier limitCompress the body or upgrade to Premium tier
ServiceCommunicationError (transient)Temporary network issueRetry with exponential backoff

Best Practices for Sending Messages

  • Always set a unique MessageId to enable duplicate detection
  • Use batch sending for high-volume message flows to reduce network overhead
  • Use Managed Identity in production — avoid hardcoding connection strings
  • Set ContentType to help receivers deserialize the body correctly
  • Set TimeToLive to prevent stale messages from accumulating in the queue
  • Wrap send operations in try-catch and retry on transient errors
  • Dispose the sender and client properly using await using or using blocks

Summary

Sending messages to Azure Service Bus requires a client connection, a sender targeting a specific queue or topic, and a message with a body and optional properties. Batch sending improves efficiency for high-volume flows. Managed Identity removes the need for connection string secrets in production. Proper error handling and retries ensure messages reach Service Bus reliably even during transient failures.

Leave a Comment