Azure Service Bus Messaging

Microsoft Azure Service Bus supports two distinct messaging patterns: Azure Relay and Service Bus Brokered Messaging. This article is an introduction to Brokered Messaging.
Brokered Messaging can decouple the communication between applications by introducing an asynchronous messaging system. The sender applications put the requests on a queue and the receivers will pick them up and process them whenever they are available. This way if the receiver application is temporarily busy or unavailable the sender application doesn’t fail or get blocked.


A queue is an entity with a head and a tail. Senders put the messages on the head and receivers pick them up from the tail.


Once a message is processed by a receiver it will no longer be available on the queue for other receivers. When there are multiple message receivers, the message load is distributed between them in a load balancing manner.

Topics and Subscriptions

Topics and Subscriptions can be thought as queues with one head but multiple tails. The head is called a Topic and each tail is called a Subscription. When a sender sends a message to a Topic, Service Bus creates multiple copies of it for each subscription. If there are several receivers interested in receiving the message, they can each listen on a different subscription and get a distinct copy of the message. However, if they listen on the same subscription, only one of them will be able to receive the message.


The Subscriptions can specify filters. This way each subscription only exposes the messages that match its filter.

Service Bus Namespace

A namespace is the way to categorize the queues and topics. You cannot create any service bus entities unless you have created a namespace first. A company may want to have different namespaces for different projects or teams. Creating a namespace is easy, you just need to go to Azure portal and follow the instructions. After the namespace is created it can be referred to, using its connection strings.


Creating Service Bus entities (Queues, Topics and Subscriptions) is also as easy as creating a Namespace. Just follow the instructions on Azure portal.

You can also manage Service Bus entities programmatically using the NamespaceManager class.

Client API

In your project install WindowsAzure.ServiceBus Nuget package to get the Service Bus client library. Here are a few code snippets to get the basic things done:

Basic Queues operations

// Creating a Queue client
var client = QueueClient.CreateFromConnectionString(connectionString, queueName);

// Creating a message
var message = new BrokeredMessage("Hello");

// Sending a message

// Receiving a message
client.OnMessage(message =>
    // Processing the message here...

Basic Topics operations

// Creating a Topic client
var topicClient = TopicClient.CreateFromConnectionString(connectionString, topicName);

// Sending a message

// Create a Subscription client
var subscriptionClient = SubscriptionClient.CreateFromConnectionString(connectionString, topicName, subscriptionName);

// Receiving a message
subscriptionClient.OnMessage(message =>
    // Processing the message here...

Messaging Factory

Another way of creating messaging clients (QueueClient, TopicClient or SubscriptionClient) is using a MessagingFactory. It allows us to create the clients in a more abstracted way and thinking of them as senders and receivers. It is more flexible and makes it easier to change the messaging strategy without having to update the code. For example, if your application is currently using Queues and you decide to switch to Topics/Subscriptions, all you need to do is updating your endpoints if you have used messaging factory to create the clients.

var factory = MessagingFactory.CreateFromConnectionString(ConnectionString);

var messageReceiver = factory.CreateMessageReceiver("entityPath");

var messageSender= factory.CreateMessageSender("entityPath");

Message Lifetime

When a message receiver is created it specifies a Receive Mode. There are two receive modes:

  • Receive and Delete: In this mode as soon as the receiver picks up the message, the message gets deleted from the queue. If the receiver crashes before being able to process the message, it will be lost. This At-Most-Once delivery is guaranteed.
  • PeekLock: This is the default mode and guarantees At-Least-Once delivery. When the receiver picks up the message in this mode, the service bus puts a lock on the message and hides it from other receivers, but the message still exists on the queue until one of the client completes processing the message. If the client crashes before that, the message will be visible on the queue again after the lock expires. The default lock duration is 30 seconds and it can be set on the receiver (queue/subscription).

After the message receiver is done with the message, it should notify the service bus by calling one of the following methods:

  • Complete(): The message was successfully processed and it should be deleted from the queue.
  • Abandon(): The receiver doesn’t know how to process the message and it returns the message to the queue to make it available for other receivers.
  • Differ(): The receiver doesn’t want to process the message just yet, so the message will be returned to the queue but it will not be delivered to any receiver unless they explicitly request for it by its sequence number.
  • DeadLetter(): The receiver has encountered an error processing the message and marks it as a dead-letter. Dead-letters are sent to a sub-queue within the same queue.

The following code shows how to read a message from the dead-letter queue:

var factory = MessagingFactory.CreateFromConnectionString(ConnectionString);
var deadletter SubscriptionClient.FormatDeadLetterPath(TopicName, SubscriptionName);
var deadletterClient = factory.CreateMessageReceiver(deadletter);
deadletterClient.OnMessage(message =>
    // Process dead-letter message here

A queue or subscription can be configured to move expired or erroneous messages to a dead-letter queue too.

The OnMessage method automatically marks any received messages completed. If the client is going to take care if this itself, the AutoComplete should be disabled first:

messageReceiver.OnMessage(message =>
        // if message processed successfully
    catch (Exception exception)
       // If message has an error

}, new OnMessageOptions
    AutoComplete = false

The longest a message can live on a queue before it is processed is determined by its time-to-live afterwhich the message gets deleted automatically. Time-to-live can be specified on the queue, topic, subscription or the message itself. A message can only live as long as the minimum time-to-live specified on its queue, topic,
subscription or the message itself.

var message = new BrokeredMessage
    TimeToLive = TimeSpan.FromMinutes(10)

Duplicate Detection

When sending a message, if an error happens and the client cannot send the message, it usually retries sending and this may lead to having duplicate messages on the system. A client also re-sends the message if it doesn’t receive any acknowledgement from the queue. Enabling duplicate detection keeps track of the MessageId property of all messages. If a new message with identical MessageId as an existing one is detected within a time window (duplicate detection history), it will be ignored and dropped.

Duplication detection can be enabled on Queue or Topic when creating them either in the Azure portal or programmatically by setting the RequiresDuplicateDetection property. The duplicate detection history window can also be set on a Queue and Topic. In the code set DuplicateDetectionHistoryTimeWindow on a QueueDescription or TopicDescription.
The duplicate detection window should be kept as small as feasible, because large window size means keeping track of more message-Ids and it impacts the throughput.

Filters, Rules and Actions

A subscription can be created with a filter so that it delivers only a subset of messages to subscription clients. A CorrelationFilter allows for a basic filtering based on the message properties like MessageId, CorrelationId, etc.

namespaceManager.CreateSubscription(topicPath, subscriptionPath,
    new CorrelationFilter { Label = "red", CorrelationId = "high"});

You can also specify a SqlFilter which allows for Sql-like expressions:

namespaceManager.CreateSubscription(topicPath, subscriptionPath,
    new SqlFilter("color = 'blue' AND quantity = 10"));

When creating a subscription, if a filter is not explicitly specified, the subscription will be created by default with a TrueFilter which means the subscription accepts all messages.
A subscription can also be created with Rule. A rule executes an Action on the messages matching the filter.

namespaceManager.CreateSubscription(topicPath, subscriptionPath,
new RuleDescription
    Name = "RedRule",
    Filter = new SqlFilter("color = 'red'"),
    Action = new SqlRuleAction(
        "SET quantity = quantity / 2;" +
        "REMOVE priority;" +
        "SET sys.CorrelationId = 'low';")

In the above example, the rule will run a SqlAction on any messages whose ‘color’ property is ‘red’ and as a result of the action, two properties of the message will be set and one property will be removed. Read more here.

Shared Access Policies

Every messaging entity is associated with a set of access policies that determine what you can do with entity. When an entity is created it comes with a default policy named RootManageSharedAccessKey which gives you full access (Manage, Send, Receive) to the entity.
Each policy has a primary key and a secondary key both of which can be used to connect to the entity. If a key is compromised, you should regenerate it and update all clients to use the new key. The reason there two keys is that you switch to the other key before regenerating one to avoid a downtime in your system.
It is not recommended to use your Root manage accessed key everywhere in your system. You should create custom policies with reasonable access levels (Send, Listen or Manage) and use it in clients.


You can use auto-forwarding to scale out an individual topic. Service Bus limits the number of subscriptions on a given topic to 2,000. You can accommodate additional subscriptions by creating second-level topics. Note that even if you are not bound by the Service Bus limitation on the number of subscriptions, adding a second level of topics can improve the overall throughput of your topic.

Auto-forwarding scenario

You can enable auto-forwarding by setting the QueueDescription.ForwardTo or SubscriptionDescription.ForwardTo properties on the source queue/subscription:

var srcSubscription = new SubscriptionDescription (srcTopic, srcSubscriptionName);
srcSubscription.ForwardTo = destTopic;

The destination entity must exist at the time the source entity is created. Lear more…

Microsoft Azure service bus messaging documentation
Microsoft Azure Service brokered messaging course on Pluralsight
Southworks by Jorge Rowies
Cloudcasts by Alan Smith
Github samples



Repository Pattern


Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes.


Use the Repository pattern to achieve one or more of the following objectives:

  • You want to maximize the amount of code that can be tested with automation and to isolate the data layer to support unit testing.
  • You access the data source from many locations and want to apply centrally managed, consistent access rules and logic.
  • You want to implement and centralize a caching strategy for the data source.
  • You want to improve the code’s maintainability and readability by separating business logic from data or service access logic.
  • You want to use business entities that are strongly typed so that you can identify problems at compile time instead of at run time.
  • You want to associate a behavior with the related data. For example, you want to calculate fields or enforce complex relationships or business rules between the data elements within an entity.
  • You want to apply a domain model to simplify complex business logic.


Best Practices

  1. Do not use IQueryable<T> as the return type of query methods. Because it creates tight coupling and you get no benefit over using the OR/M directly. Use more generic types like IEnumerable<T>.
  2. Create repositories for domain aggregates only not for every single entity. If you are not using Aggregates in a Bounded Context, the repository pattern may be less useful.
  3. Creating base types for repositories is not recommended. If it is needed make sure not breaking the Interface Segregation Principle.
  4. It is not recommended to create generic repositories, make sure you have a good reason if you want to create one.
  5. Repositories must return domain entities which are usable in the domain services without having to be converted, so any data contracts must be converted to domain entities before the repository returns them.
  6. Apart from CRUD operations, repositories can also have identity generator, count methods or finder methods.
  7. A repository should only have the minimum required operations. It doesn’t even have to include all the four of CRUD operations. It can be as simple as a repository with only one operation.
  8. It is OK to have bulk methods for adding or removing multiple items to or from the repository.
  9. If you find that you must create many finder methods supporting use case optimal queries on multiple Repositories, it’s probably a code smell. First of all, this situation could be an indication that you’ve misjudged Aggregate boundaries and overlooked the opportunity to design one or more Aggregates of different types. However, if you encounter this situation and your analysis indicates that your Aggregate boundaries are well designed, this could point to the need to consider using CQRS.
  10. Do not design a Repository to provide access to parts that the Aggregate Root would not otherwise allow access to by way of navigation.
  11. Place the repository interface definition in the same Module (assembly) as the Aggregate type that it stores. The implementation class goes in a separate Module. The following image shows how the dependencies should be 
  12. Generally speaking, there is a one-to-one relationship between an Aggregate type and a Repository.
  13. If the aggregate includes large members, for example, big lists of items, you can consider lazy loading.
  14. The only responsibility of a repository is data persistence, so no business (domain) logic should be added to a repository. The operations are CRUD only. This also applies to the name of the methods.


Successful Backend Architecture

This is a clean architecture and is a simplified version of onion architecture. It is also conforming to the principals of Hexagonal Architecture.


In the following diagram the arrows show the direction of the dependencies. Any outer layer can directly call ANY inner layer. So the yellow layer (Adapters layer) can rely on all of the other layers. The application layer can only have dependency on the domain layer. And the domain layer should NOT have any references to the other layers. Any communication with the outside word happens in the Adapters layer.



Adapters layer

This layer makes it possible for the application to communicate with the outside word. In order to interact with external components like databases, web, files system, etc. the application needs a layer which can convert its internal objects to something which is understandable by the external components and vice versa. For example a Data Access is needed to let the application talk to a database; or to be able to expose the application’s functionality through the Web, we need to create a Web Service which makes use of the .Net Framework web technologies. These components are called Adapters and they should reside in the Adapters layer. The inner layers or other adapters cannot have dependencies on this layer.


As the above diagram shows, there are two groups of external components: driving actors and driven actors (external resources). A Driving actor is an actor that drives the application (take it out of quiescent state to perform one of its advertised functions). End users, automated tests, or remote clients are a few examples of driving actors. Whereas a driven actor is one that the application drives, either to get answers from or to merely notify. Database, files system or remote web services are some examples of driven actors (a.k.a external resources). The distinction between “driving” and “driven” lies in who triggers or is in charge of the conversation. These two groups of the external components require two groups of adapters: Driving adapters and Driven adapters.

Driving Adapters

These are the adapters that expose the applications functionality to the outside world. In other words it allows the driving actors to drive the application. The other layers of the application never need to see this layer, however the driving adapters need to have dependency on them. The following list encompasses the driving adapters:

  • Web Service: Regardless of the web service technology, all of the web services go to this layer. Web API, WCF, or Soap (ASMX). This layer must not have any business or application logic and should be as thin as possible. The consumer of this layer is remote clients.
  • Tests: They are another residents of this layer. They call the functions of other layers and allow the test runners drive the application for test purposes. So the test runners are the driving actors of this layer.
  • Presentation: This layer can have the adapters that translates the user’s keystrokes and gestures into data understandable for the application and visualize the application’s output to the user. The actor who drives this layer is the end user.


The driving adapters are where the composition root of the entire application should go. Any service registration happens in this layer.

Driven Adapters (Infrastructure)

This layer has the concrete implementation of the dependencies of the other layers. Infrastructure is any code that is a commodity and does not give your application a competitive advantage. This code is most likely to change frequently as the software goes through years of maintenance. That’s why no other layer should have any dependency on this. Any dependency to this layer must be through abstractions. For example if the software needs a repository, it should use an abstract repository (i.e. an interface) and the implementation of the repository goes to this layer. We rely heavily on the Dependency Inversion principle. The application core needs an implementation of core interfaces, and since those implementing classes reside at the edges of the application, we need some mechanism for injecting that code at runtime.

  • Data Access: This layer has the implementation of the repositories. They can persist and retrieve the domain objects in some storage. Depending on what storage to use, we may need adapters (different implementation for the repository).
  • Service Proxy: Whenever we add a service reference to the application, a proxy component is generated which is an adapter between the application and the remote service. It makes it possible to send and receive the messages throw the web. Depending on the messaging technology, we may need different adapters here. Be it SOAP, TCP or even a message queue, the application should not need to change because of a change in the underlying messaging technology.
  • File Access is another example of infrastructure. It makes it possible to operate the file system regardless of the contents of the files.

Note: The adapters in the infrastructure layer should be substituted for test doubles when testing the application.



Application layer (Orchestrator)

This layer contains the application services which are single responsibility classes that do the orchestration of the application and deal with application logic. These services are different from the web services that we have in the Web Service Layer. Please be advised that this layer is not meant to have any domain (a.k.a business) logic. Domain logic should go to the Domain Layer.

  • We define the DTO classes (request/response) in this layer.
  • Application services are also responsible for composing the response objects.
  • As a naming convention suffix them with the word “ApplicationService” or just “Service”. But make it consistent.
  • Application services can consume repositories and other domain services.
  • Although it does’t see the infrastructure layer, it can see its abstractions.

Domain layer (Business layer)

This layer will have all of the domain models: Entities, values objects, domain events, and the domain exceptions. The abstraction of the repositories also go to this layer. The business rules should be applied in this layer.

Why this architecture

It is a clean architecture that means it can produce a system which is:

  1. Independent of Frameworks. The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.
  2. Testable. The business rules can be tested without the UI, Database, Web Server, or any other external element.
  3. Independent of UI. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
  4. Independent of Database. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
  5. Independent of any external agency. In fact your business rules simply don’t know anything at all about the outside world.

The Dependency Rule

The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies.

The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in the an inner circle. That includes, functions, classes. variables, or any other named software entity.

By the same token, data formats used in an outer circle should not be used by an inner circle, especially if those formats are generate by a framework in an outer circle. We don’t want anything in an outer circle to impact the inner circles.

Key tenets

The following tenets are those of the onion architecture. Our architecture should adhere to all of them as it is a simplified version of onion:

  1. The application is built around an independent object model
  2. Inner layers define interfaces. Outer layers implement interfaces
  3. Direction of coupling is toward the centre
  4. All application core code can be compiled and run separate from infrastructure


Hexagonal Architecture:
Onion Architecture:
Clean Architecture: