CQRS in Azure - Part 4

In CQRS in Azure Part 1, CQRS was defined and context was provided to explain why the pattern is relevant to building solutions in Azure.  CQRS in Azure - Part 2 and CQRS in Azure - part 3 illustrates the pattern by using a fictitious inventory system in order provide potential strategies for addressing the challenges that arise when moving away from the traditional monolith solution.  This post expands upon some of the advantages when CQRS is applied at the service level.

A sample project illustrating some of the approaches described is available on MSDN Samples: CQRS in Azure.

Greater Agility

One of the biggest advantages of CQRS at a service level is the potential of improving the agility of the Software Development Lifecycle (SDLC).  In splitting the solution into smaller isolated components, the opportunity to develop and deliver the components in a more agile manner is increased as this allows for different areas of the solution or domains to be developed with limited impact on each other.  Depending on how the development teams are structured, this could also allow for teams to specialize in a particular horizontal or technical slice of the solution (e.g., database or MVC) or a vertical or functional slice (e.g., payments or account management).

In the Old Pie Shoppe example, this allowed for the command to be handled in an Azure Function while the query to be handled in a MVC web application.  To further illustrate, imagine after the design of the Old Pie Shoppe dashboard, the requirements could be delivered to two different teams and the solution developed in parallel.  This was achieved by reducing the number of dependencies between the two actions: get the inventory information and update an inventory amount.  In a traditional monolith, the two services would be hosted on the same platform and share many of the same development layers (re., data access layer, business layer) and technologies (re., entity framework, mvc).  This forces an organization to be constrained in their options both in how they build and how to deliver the solution.  By splitting into services that can be developed, delivered and maintained independently, more options are available which increases the agility of the SDLC.

Reduce Complexity

By limiting the scope of a component to a clear responsibility, the aim is to reduce the complexity for both the query and command operations.  In large scale application development a reduction in complexity contributes to better maintainability and increases the longevity of  a solution.  Components with less responsibility are also easier to unit test and simpler to extend without adversely affecting existing functionality.

Different Domain Models

By implementing the query separate from the command, the two component do not have to share the same domain model or implementation.  In some circumstances this could have a significant impact by allowing for different technologies to be chosen that best suits the situation.

To emphasize the significance of this, the Old Pie Shoppe example project the web application (MVC) solution used an object-relational mapper (Entity Framework) where the Azure Function used ADO.Net to insert directly into the inventory entry table.  This allowed for the database to have a fine grained level of security to only allow the MVC web application read access and only allow the Azure Function the ability to insert into the inventory entry table.

Independently Scalable

The requirement to handle large fluctuation in scale is a more common requirement especially with public facing solutions.  Having the ability to scale different features of a solution independently is a powerful strategy to achieve this.

As stated in Post 1, the ability to scale the command separate from query was an important factor in using the CQRS pattern.  As both components are deployed as app services, they both have the ability to scale up (changing the size and features of the app service plan) and scale out (increasing or decreasing the number of app instances).

Conclusion

The aim of the CQRS in Azure posts was to provide an illustration of how CQRS could be applied to developing solutions in Azure and was particularly aimed at the conceptually transition from traditional monolithic application development to an application built upon microservices.  As with all guidance type posts, each circumstance is unique so there is no right or wrong way to develop solutions but hopefully this post will help some designers and developers look at a problem in a slightly different way.  Also as more technology allows direct access via APIs, the opportunity to apply microservice patterns and/or gain the benefit of accessing resources outside of the core solution is increased.  As an example, the Azure Storage Javascript Client Library provides the ability to directly access storage from client side scripts.

Additional Resources

This series was about applying CQRS at the service level.  There are some great resources about applying CQRS within an application including an excellent presentation from Ignite 2016: Exploring CQRS and Event Sourcing: A journey into high scalability, availability, and maintainability with Microsoft Azure.  This presentation applies CQRS within an MVC application to provide a highly extendable, modular framework for building event driven applications.

Related to using CQRS within an application:

Additional resources on benefits of CQRS:

Thoughts, comments, alternatives not provided; please comment below.  Cheers!