Microservice Architecture & Domain Driven Design. Aggregates and ‘Decompose by Subdomain’ Pattern
Domain Driven Design Theory on Microservices, Aggregates and ‘Decompose by Subdomain’ Pattern.
In the previous article From Monolithic to a Microservice Architecture. How to Decompose using ‘Branch By Abstraction’ Pattern, we decomposed a monolithic Quarkus e-commerce application into a small microservice architecture with 2 microservices orders-service and inventory-service, using ‘Branch by Abstraction’ pattern and ‘Database as a Service’ pattern.
The purpose of that tutorial for simplicity was to show you the ‘Branch by Abstraction Pattern’ in programming terms, and explore some of the Quarkus advantages, and by no means the implementation is a production-grade.
There is still tight coupling between microservices, exception handling is missing, both databases luck eventual consistency mechanisms, synchronous communication between microservices is kind of anti-pattern, SOILD is not strictly enforced etc.
Still our order-service, is the Big Ball of Mud in Domain Design Terms, which means is still that monolithic spaghetti code. What we have managed to achieve is to extract the warehouse-inventory functionality into a new microservice called inventory-service, using synchronous communication in between. We need to go into the Domain Driven Design territory which will help us derive and construct our microservices in a proper way.
In this article, I will do my best to explain the theory of Domain Driven Design and the ‘Decompose by Subdomain’ Pattern as well as the ‘Aggegate ’. I leave behind BoundedContexts, Strategic Design, Context Mapping, for another article and starting from the real deal for a us the ‘CRUD’ thinking programmers:
The real deal are Aggregates and Subdomains, the theory behind and how they relate to microservices.

Ancient Greek Philosophy & Domain Driven Design
Domain Driven Design is like reading Plato. It is hard to read, with abstract terminology and philosophical terms, jumping from the ‘concept’ phase to ‘solution’ space in one phrase. As a Greek the only thing I can say about DDD is:
Eric Evans is the Software Engineer Philosopher from Ancient Greece, engaging in insightful conversations with visionaries like Plato, possibly a student of Plato , and eventually writes the book “Domain-Driven Design: Tackling Complexity in the Heart of Software”.
While Eric Evans may not be an ancient Greek philosopher, his work on Domain-Driven Design (DDD) is JUST AMAZING.
He actually gave birth to the concept of DDD. This methodology emphasizes a deep understanding of the domain in which the software operates, and it encourages collaboration between technical and non-technical stakeholders to create a shared understanding of the problem space.
In a sense, one could draw a parallel between the philosophical dialogues of ancient Greece, where scholars engaged in discussions to understand fundamental concepts, and the collaborative approach advocated by DDD to gain a shared understanding of the domain in software development.
Whether modern software engineering or ancient philosophy, the pursuit of understanding and clarity seems to be a common thread!
The only difference from Ancient Greek Times is that our mind, for years, automatically works in ‘CRUD’ mode of implementing things for 20 years. But now if we really want to properly design a micro-service architecture it is time to start thinking in terms of Domain Driven Design.
What is a Domain Model
Definition:In Domain-Driven Design (DDD), the Domain Model it is a conceptual model of the problem domain, which is the specific area or subject matter that the software is designed to address.
Another difficult terminology. Let’s clear the confusion behind it.
Conceptual means that all the people involved domain experts, programmers, users, clients sit together and do an analysis of the problem trying to identify the core functionality the relationships between etc. That is basically our ‘Domain’.It consists basically of diagrams and documentation about the problem. In ‘conceptual problem’ space. But what is the actual implementation of it?
The ‘Domain Model’ is the actual implementation of the ‘Domain’.
The Subdomains. Distilled knowledge of the Domain.
The Domain is broken down into smaller pieces-problems where the knowledge is concentrated on a small part of the big problem named Subdomains.
Now we have a distilled knowledge of a specific part of the problem, and again we have more documentation and more diagrams but this time there is an important characteristic:
A Common Business Language
The language that we speak between the participants is common and that language is called the Ubiquitous language.
In Subdomain everybody can understand the key entities and the relationships between because the vocabulary is common, and the focus is on a small piece of functionality.
But how to implement the functionality of a Subdomain Model?
Subdomain Model. An One-to-One Mapping with a MicroService.
Considering Chris Richardson’s theory and the “Decompose by Subdomain Pattern” :
“Define services corresponding to Domain-Driven Design (DDD) subdomains. DDD refers to the application’s problem space — the business — as the domain. A domain is consists of multiple subdomains. Each subdomain corresponds to a different part of the business [4].”
What Chris says is that:
take all the documentation and your functional and nonfunctional requirements which construct the distilled knowledge of a Subdomain and start implementing that Subdomain as a microservice

In DDD all the core business logic of one micro-service is implemented inside of the ‘Domain Layer’ of our ‘Subdomain Model’. That ‘Domain Layer’ includes Aggregates, Entities, Domain Services, Domain Events, Repositories and Value Objects as we will see later on.
Categorize Subdomains.
Each of these Subdomains can be categorized as either Core, Support, or Generic.
To categorize our subdomains we follow the below mental process.
- We must Identify Core Business Capabilities: Determine the core functions and capabilities of the business. These are the areas that directly contribute to the organization’s value proposition and competitive advantage. Core Subdomains are those that relate to these essential business functions.
The Order Subdomain is a Core Subdomain candidate. Without it an ecommerce site cannot exist!
2. We must Identity Supporting Business Functions: Identify Subdomains that are not directly core to the business but still play a supporting role. These Subdomains provide necessary services or functions that assist the core business capabilities. They may not be unique to the business but are crucial for its operation.
Looks like without Catalog to be presented to the User or a Warehouse /Inventory system to check for stock availability an e-commerce application cannot operate. Thus in order to support the Domain our Support Subdomain candidates are Warehouse, Catalog.
3. We must find the Generic or Shared Subdomains: Some Subdomains might be common across various industries or organizations. These can be considered as Generic Subdomains.
Generic Subdomain candidates are Authentication, Invoicing-Payments and Customer which can be reused in other Domains. There is not need to re-write code for authentication or payments each time we are dealing with a new Domain problem. We might also purchased them from an external vendor such as a Customer CRM or a payments Gateway and an invoicing ERP.
Distilled Knowledge: Based on the above theory we can summarize the following rules about Subdomain Models:
1) A Domain Model can be Split into Subdomain Models. 2) Each Subdomain Model maps-one-to one with a microservice. 3) Each Subdomain Model has a common vocabulary and solves a specific business problem. 4) The Subdomain Model contains classes, with related context such as: - Entities which are objects that have ID, such as Order, OrderItem - Value objects, which are objects that don’t have ID like OrderStatus - Repositories such as the OrderRepository - Groups of the above named ‘Aggregates’ such as the OrderAggregate - Services (Where Business Logic is implemented), Domain and Subdomain. Events and Handlers - Events to communicate between domain services and microservices in other bounded contexts.
The most important part of a Subdomain is the Aggregate which encapsulates the most important part of the business logic of our microservice. Lets dive in.
What is an Aggregate?
In the context of Domain-Driven Design (DDD), an aggregate is a fundamental concept that plays a pivotal role in modeling complex domains. It is mostly misunderstood by is the key to unlock the real power of Domain Driven Design. Aggregates exists inside the Domain Layer of our micro-service.
According to Vaughn Vernon in his book “Implementing Domain-Driven Design”],
“an aggregate is a cluster of related domain entities that are treated as a single unit for data changes. This encapsulation of domain logic within aggregates ensures data consistency and integrity [2].”
Since our micro-service maps one to one with a Subdomain, based on the above quote the Aggregate is actually
The Core Of Our Micro-Service Business Logic
Furthermore, Eric Evans, in “Domain-Driven Design: Tackling Complexity in the Heart of Software,” highlights the importance of “aggregates as boundaries for transactional consistency [1].”
Based on these quotes it is easy to understand that aggregates in Domain-Driven Design (DDD) ensure that all elements within a single Aggregate are consistent with business rules when a transaction is committed to the database.
The figure below represents a typical Aggregate in an e-commerce scenario in Domain Driven Design. The blue line represents the transaction boundary of the Aggregate. The microservice references other Aggregates of other Subdomains using the ‘reference by identity pattern’.

Aggregate as a Transactional Consistency Boundary
While it’s possible to include elements within an Aggregate that don’t require consistency after a transaction, the primary concern is maintaining transactional consistency.
The outer boundary of each Aggregate represents a separate transaction responsible for persisting all the objects within that Aggregate.
But what exactly is a transaction? As Vernon quotes:
“transaction is how modifications to an Aggregate are isolated and how business invariants — the rules to which the software must always adhere — are guaranteed to be consistent following each business operation. Whether this requirement is controlled by an atomic database transaction or by some other means, the Aggregate ’s state, or its representation by means of Event Sourcing, must be safely and correctly transitioned,and maintained at all times [3, p. 73].”
Vernon Quote Analysis.
Lets’s outline some key ideas on that quote:
- Transaction:
Order has 2 OrderItems (OrderLines), and the first OrderItem has 1 Mac Mini and the other one has 2 IPhone 14 Pros for my kids. The state should be consistent and maintained in a single ACID transaction, whenever I want to add a new product lets say a third IPhone for my ex-wife :) (noooo……..!)
2. Business inariants (RULES): The following rules should must be consistent every time the state changes, e.g a new product is added or removed.
— The total cost of the Order is the sum of the cost of each OrderItem. — Order must always have a minimum 1 OrderItem — OrderItem must always have a minimum 1 Product. — The total cost of OrderItem is equal to the multiplication of the price of single product times quantity requested.
3. Aggregate ’s state representation (STATE STORE IMPLEMENTATION MECHANISM): This is very important. It actually differentiates and categorizes the Aggregates based on the mechanism to store and load the state of the Aggregate. The two categories are:
— STATE_STORED Aggregates using normal ORM techniques — EVENT_STORED Aggregates using complex event-sourcing techinques
Tip:Regarding 3, the concept of a “transaction” is flexible and can be implemented differently depending on the application architecture. In some cases, an Application Service may manage atomic database transactions (thus STATE_STORED Aggregates), while in other architectures like the Actor model, Event Sourcing may be used (thus EVENT_STORED Aggregates), even in databases without native atomic transaction support.
Regardless of the transaction implementation method used, the core idea of a “transaction” is to ensure that modifications to an Aggregate are isolated, and that business invariants are consistently maintained after each business operation.
Distilled Knowledge: Based on the above theory we can summarize the following rules about Aggregates:
1) They are Clusters of related Entities and value objects 2) The cluster is treated as a single unit. 3) They provide a boundary for transactional consistency. 4) They provide a business logic boundary by encapsulating business rules and forcing them to be consistent. 5) They are categorized based on the state saving-restore implementation mechanism been used. Therefore we have Stated-Stored Aggregates and more complex Event-Store Aggregates. 6) They contain only ONE AggregateRoot.
I thought I understand Bounded Contexts.
Well, i’m still struggling to understand Bounded Contexts, thus I choose not to write much about them. Bounded Contexts lay in the ‘solution space’. Domains lay in the ‘problem space’.
For me a ‘A Bounded Context’ is a conceptual boundary within the terms and models are well-defined and consistent.
Subdomain and Bounded Context Relation. I prefer for the solution space to use the term ‘Subdomain Model’ for the implementation, and not ‘Bounded Context’. Thus, I consider that each Subdomain would have its own Bounded Context. This is the ideal one-to-one mapping between a Subdomain Model and a Bounded Context.
Summary
Having all these knowledge still is a kinda of puzzle pieces.All the puzzle pieces come together in the next article — “Quarkus. Microservices & DDD Hexagonal Architecture. How to Build your Hexagon Layers. The ‘Framework Hexagon’. Part 1.” — as we dive deep into coding the building blocks of a ‘Subdomain Model’ using the Hexagonal Architecture and Quarkus.
Thank you for your time!
Bibliography
[1]E. Evans, Domain-driven design : tackling complexity in the heart of software. Boston, Mass. ; Munich: Addison-Wesley, 2003.
[2]V. Vernon, Implementing domain-driven design. Upper Saddle River, Nj: Addision-Wesley, 2013.
[3]V. Vernon, Domain-Driven Design Distilled, 1st ed. Addison-Wesley Professional, 2016.
[4]C. Richardson, “Pattern: Decompose by Subdomain Context,” Microservices.io. https://microservices.io/patterns/decomposition/decompose-by-subdomain.html (accessed Oct. 10, 2023).





