Service Bus Message Structure

A message is the unit of data that travels through Azure Service Bus. Every message carries two things — a body (the actual data) and properties (metadata about the data). Understanding the full message structure helps in designing systems that route, filter, track, and expire messages correctly.

Message Anatomy

+------------------------------------------------------+
|                 SERVICE BUS MESSAGE                  |
|------------------------------------------------------|
|  BODY (Payload)                                      |
|  { "orderId": 101, "product": "Laptop", "qty": 2 }  |
|------------------------------------------------------|
|  SYSTEM PROPERTIES (Set by Service Bus)              |
|  MessageId         : abc-001                         |
|  SequenceNumber    : 1                               |
|  EnqueuedTime      : 2024-01-15T10:30:00Z            |
|  DeliveryCount     : 1                               |
|  LockedUntilUtc    : 2024-01-15T10:31:00Z            |
|------------------------------------------------------|
|  USER PROPERTIES (Set by the Sender)                 |
|  Region            : India                           |
|  Priority          : High                            |
|  OrderType         : Express                         |
|------------------------------------------------------|
|  BROKER PROPERTIES (Behavior Settings)               |
|  Subject/Label     : NewOrder                        |
|  ContentType       : application/json                |
|  TimeToLive        : PT30M (30 minutes)              |
|  ScheduledEnqueueTime: 2024-01-15T11:00:00Z          |
|  SessionId         : customer-456                    |
|  CorrelationId     : request-789                     |
|  ReplyTo           : response-queue                  |
|  PartitionKey      : customer-456                    |
+------------------------------------------------------+

1. Message Body

The body carries the actual data the sender wants to deliver to the receiver. The body is a sequence of bytes. The sender decides the format — JSON, XML, plain text, or binary.

JSON Body Example

{
  "orderId": 101,
  "customerId": "C456",
  "product": "Laptop",
  "quantity": 2,
  "totalAmount": 1200.00,
  "region": "India"
}

Set the Body in .NET

// From string
var message = new ServiceBusMessage("Hello, Service Bus!");

// From JSON object (use BinaryData)
var order = new { orderId = 101, product = "Laptop" };
var json = System.Text.Json.JsonSerializer.Serialize(order);
var message = new ServiceBusMessage(BinaryData.FromString(json));
message.ContentType = "application/json";

2. System Properties (Read-Only)

System properties are set and managed by Azure Service Bus. Senders cannot set these values. Receivers read them to understand the message state.

PropertyTypeDescription
SequenceNumberlongUnique, monotonically increasing number assigned by Service Bus
EnqueuedTimeDateTimeOffsetThe time the message entered the queue or topic
DeliveryCountintHow many times the message was delivered (increases on each retry)
LockedUntilUtcDateTimeOffsetWhen the message lock expires (receiver must complete before this)
StateenumActive, Deferred, or Scheduled
DeadLetterReasonstringWhy the message was dead-lettered (visible in Dead Letter Queue)

3. Broker Properties (Sender-Configurable Behavior)

Broker properties control how Service Bus handles the message. Senders set these before publishing.

PropertyPurposeExample
MessageIdUnique identifier — used for duplicate detectionorder-101-2024
Subject (Label)Short description of the message — used for routing and filteringNewOrder
ContentTypeMIME type of the body — helps receiver deserialize correctlyapplication/json
TimeToLiveHow long the message stays before expiringPT30M = 30 minutes
ScheduledEnqueueTimeDelay delivery — message becomes visible at this time2024-01-15 at 11:00 AM
SessionIdGroups messages into a session for ordered processingcustomer-456
CorrelationIdLink reply messages back to original requestsrequest-789
ReplyToName of queue or topic where the receiver should send its replyorder-response-queue
PartitionKeyRoutes message to a specific partition — set same as SessionId for sessionscustomer-456

4. User-Defined (Application) Properties

Application properties are custom key-value pairs attached by the sender. These are indexed and available for SQL filter expressions on topic subscriptions. They do not affect how Service Bus handles the message internally.

// Set custom properties (.NET)
var message = new ServiceBusMessage("Order data here");
message.ApplicationProperties["Region"]    = "India";
message.ApplicationProperties["Priority"]  = "High";
message.ApplicationProperties["OrderType"] = "Express";
message.ApplicationProperties["Amount"]    = 1200.00;

These properties can then be used in SQL filters on topic subscriptions:

Filter: "Region = 'India' AND Amount > 500 AND Priority = 'High'"

MessageId and Duplicate Detection

The MessageId is the most important property for preventing duplicate messages. When a sender sets a unique MessageId and Duplicate Detection is enabled on the queue or topic, Service Bus rejects any message with a MessageId it has already seen within the duplicate detection window.

Sender sends:  MessageId = "order-101"  --> Accepted (first time)
Sender sends:  MessageId = "order-101"  --> REJECTED (duplicate detected)
Sender sends:  MessageId = "order-102"  --> Accepted (new, unique ID)

CorrelationId — Request-Reply Pattern

The CorrelationId implements the request-reply pattern. The sender sends a request with a unique MessageId. The receiver sends a reply message and sets the CorrelationId to match the original MessageId. The original sender identifies which reply belongs to which request.

Step 1: Sender sends request
        MessageId    = "req-001"
        ReplyTo      = "response-queue"

Step 2: Receiver processes request and sends reply
        MessageId    = "resp-001"
        CorrelationId = "req-001"   (matches the original request)

Step 3: Original sender reads response-queue
        Finds message where CorrelationId = "req-001"
        Knows this reply belongs to its original request

SessionId — Ordered Grouped Messages

The SessionId ties related messages together into a logical group called a session. All messages with the same SessionId go to one consumer in the order they were sent.

Order 101 messages:
  Step 1: { SessionId: "order-101", body: "ItemAdded"    }
  Step 2: { SessionId: "order-101", body: "PaymentDone"  }
  Step 3: { SessionId: "order-101", body: "OrderShipped" }

Consumer gets all three in sequence: ItemAdded → PaymentDone → OrderShipped

TimeToLive — Message Expiry

Every message has a TimeToLive (TTL) value. Once the TTL expires, the message is no longer visible to consumers. If Dead-Lettering on Message Expiration is enabled on the queue or subscription, the expired message moves to the Dead Letter Queue. Otherwise, it is permanently deleted.

Message TTL: 30 minutes
Message sent at: 10:00 AM

10:00 AM --> Message visible in queue
10:30 AM --> Message expires (TTL reached)

If Dead-Lettering on Expiry = ON:
  --> Message moves to Dead Letter Queue

If Dead-Lettering on Expiry = OFF:
  --> Message deleted permanently

Complete Message Example (.NET)

var message = new ServiceBusMessage(BinaryData.FromString(json))
{
    MessageId           = "order-101",
    Subject             = "NewOrder",
    ContentType         = "application/json",
    TimeToLive          = TimeSpan.FromMinutes(30),
    SessionId           = "customer-456",
    CorrelationId       = "request-789",
    ReplyTo             = "order-response-queue",
    ScheduledEnqueueTime = DateTimeOffset.UtcNow.AddMinutes(5)
};

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

Summary

An Azure Service Bus message consists of a body carrying the payload, system properties managed by the broker, broker properties that control delivery behavior, and application properties for custom routing and filtering. Setting properties like MessageId, SessionId, TimeToLive, CorrelationId, and Subject correctly enables advanced features like duplicate detection, ordered sessions, scheduled delivery, and request-reply communication patterns.

Leave a Comment