Azure Service Bus: Delivery Count, Transactions, and Cross-Entity Transactions

Delivery Count
Delivery Count is a crucial feature in Azure Service Bus that helps manage message processing reliability. Each time a message is delivered to a receiver, its delivery count increases. If the delivery count exceeds a specified threshold (set by the MaxDeliveryCount
property of the queue or subscription), the message is moved to the Dead-letter Queue (DLQ).
Practical Usage
- Scenario: If a message cannot be processed successfully after several attempts, it is moved to the DLQ for further inspection, preventing it from being retried indefinitely.
// Example: Checking the delivery count of a message
const deliveryCount = message.deliveryCount;
console.log(`This message has been delivered ${deliveryCount} times.`);
Transactions
Transactions in Azure Service Bus ensure atomicity of operations, which means that a set of operations either all succeed or all fail as a single unit.
Features of Transactions
Atomicity: Multiple operations (e.g., send and complete messages) are treated as a single transaction.
Consistency: Guarantees that the system remains in a valid state after the transaction.
How to Use Transactions in Node.js
To perform transactional operations, you can use the ServiceBusClient
to initiate a transaction scope.
import { ServiceBusClient } from '@azure/service-bus';
const serviceBusClient = new ServiceBusClient(process.env.SERVICE_BUS_CONNECTION_STRING);
const sender = serviceBusClient.createSender("queue-name");
async function sendMessageWithTransaction() {
const session = await serviceBusClient.createSession();
await session.start();
const transactionContext = await session.createTransactionContext();
try {
await sender.sendMessages({ body: "Transactional message" }, { transactionContext });
await transactionContext.commit();
console.log("Transaction committed successfully.");
} catch (error) {
await transactionContext.rollback();
console.log("Transaction rolled back.");
} finally {
await session.close();
}
}
sendMessageWithTransaction();
Rollback Transaction
Rollback is used to revert all operations performed in a transaction. If any part of a transaction fails, a rollback ensures that none of the operations take effect, maintaining data integrity.
Example:
// Rolling back a transaction
try {
await transactionContext.commit();
} catch (error) {
await transactionContext.rollback();
console.log("Transaction rolled back due to an error.");
}
Use of Transaction Scope Async Flow Option
The Transaction Scope Async Flow Option allows asynchronous code within a transaction scope to maintain its context across asynchronous calls. This ensures that all operations within the asynchronous flow participate in the same transaction.
Example in Node.js:
import { ServiceBusClient } from '@azure/service-bus';
async function processMessagesInTransaction() {
const session = await serviceBusClient.createSession();
const transactionContext = await session.createTransactionContext();
try {
// Asynchronous operations
await sender.sendMessages({ body: "Message 1" }, { transactionContext });
await sender.sendMessages({ body: "Message 2" }, { transactionContext });
await transactionContext.commit();
console.log("Transaction committed with async flow.");
} catch (error) {
await transactionContext.rollback();
console.log("Transaction rolled back with async flow.");
} finally {
await session.close();
}
}
processMessagesInTransaction();
Cross-Entity Transactions
Cross-Entity Transactions allow you to perform transactional operations across multiple entities (e.g., queues and topics) within the same transaction. This is particularly useful when you need to ensure consistency across different messaging entities.
Example:
import { ServiceBusClient } from '@azure/service-bus';
async function crossEntityTransaction() {
const session = await serviceBusClient.createSession();
const transactionContext = await session.createTransactionContext();
try {
// Sending to multiple entities
await sender1.sendMessages({ body: "Message to Queue 1" }, { transactionContext });
await sender2.sendMessages({ body: "Message to Queue 2" }, { transactionContext });
await transactionContext.commit();
console.log("Cross-entity transaction committed successfully.");
} catch (error) {
await transactionContext.rollback();
console.log("Cross-entity transaction rolled back.");
} finally {
await session.close();
}
}
crossEntityTransaction();
Summary
Delivery Count: Tracks how many times a message is delivered; messages exceeding
MaxDeliveryCount
are moved to the DLQ.Transactions: Ensure atomic operations across multiple Service Bus operations.
Rollback: Reverts all operations in a transaction if any part fails.
Transaction Scope Async Flow: Maintains transaction context across asynchronous operations.
Cross-Entity Transactions: Enable transactional operations across multiple queues and topics.
These features enhance the reliability and consistency of message handling in Azure Service Bus, making it a robust solution for enterprise-grade messaging.
Subscribe to my newsletter
Read articles from Muhammad Sufiyan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Muhammad Sufiyan
Muhammad Sufiyan
As a former 3D Animator with more than 12 years of experience, I have always been fascinated by the intersection of technology and creativity. That's why I recently shifted my career towards MERN stack development and software engineering, where I have been serving since 2021. With my background in 3D animation, I bring a unique perspective to software development, combining creativity and technical expertise to build innovative and visually engaging applications. I have a passion for learning and staying up-to-date with the latest technologies and best practices, and I enjoy collaborating with cross-functional teams to solve complex problems and create seamless user experiences. In my current role as a MERN stack developer, I have been responsible for developing and implementing web applications using MongoDB, Express, React, and Node.js. I have also gained experience in Agile development methodologies, version control with Git, and cloud-based deployment using platforms like Heroku and AWS. I am committed to delivering high-quality work that meets the needs of both clients and end-users, and I am always seeking new challenges and opportunities to grow both personally and professionally.