Be careful with Domain Events

Technical blog from UNIL engineering teams
6 min readJun 19, 2023


Photo by Paolo Chiabrando on Unsplash

Many examples of Domain-Driven Design implementation will start with a technique known as Event Storming. This automatically puts the concept of Domain Events at the very center of the design. This article presents some counter arguments for event-centric modeling in DDD.

Event Storming and “Deep Model”

Some 10 years after Eric Evans published his Domain-Driven Design: Tackling Complexity in the Heart of Software, Alberto Brandolini introduced the technique of Event Storming. This technique, in combination with the Domain Events pattern, is now quite popular DDD practice. However, in the original work of Evans there is no notion of Domain Events, at least, not in the way it has been used as a tactical design pattern in domain modeling. Foremost preoccupation for Evans has always been to elucidate the core of the domain by examining and analyzing the structure of and relationship among its constitutive elements. This analysis is greatly facilitated by the use of Ubiquitous Language shared among domain experts and developers. But there is another absolutely essential principle which should govern any model analysis. It is something which Evans calls “deep model” and which he illustrates with several explicit examples in his original work.

It is important to realize that the fondamental insight which brings into light the deep underlying model of the core domain will not come by magic. It can only dawn upon a developer after several trial and errors and after she has thoroughly studied the specific problem space. One can successfully model something only after one has learned the concrete reality of the underlying phenomena. The context of any business operation, its terminology and its rules must be understood in their essence before any meaningful model can be invented.

Let’s look at one of the examples presented by Evans in the blue book. There is a canonical implementation of Cargo tracking example available in DDDSample repository. Here is what we can read as the description of Delivery class in that implementation (copied here from original source code for convenience):

* The actual transportation of the cargo, as opposed to
* the customer requirement (RouteSpecification) and the plan (Itinerary).
public class Delivery implements ValueObject<Delivery> {
// code omitted

And here is an attempt at visualizing aggregates and relations involved in the solution presented in DDDSample:

Diagram of aggregates in Cargo domain implemented by DDDSample (copied here from clean-cargo repository).

Delivery is a very intricate object which ties together a number of other key abstractions from the Cargo domain. It’s a result of a deep modeling insight which allows for a correct correlation between “actual transportation” (a series of actually occurred movements of a cargo through geographically determined Leg s) and the “route specification” and “itinerary” as has been specified by “customer requirement”. Almost all invariants in Cargo aggregate will involve some logic implemented in Delivery and most of the business functionality for the cargo tracking bounded context will depend on it.

Coming up with Delivery value object, especially the way it encapsulates other value objects and embodies the relationship between Cargo , Voayage, Location , and HandlingEvent aggregates — is an example of an “ah-ha moment”, an breakthrough insight which unlocks an elegant solution for the Cargo tracking problem.

The point is: the solution revolving around Delivery value object in Cargo tracking problem space was introduced without the use of Event Storming. It most certainly did result from many discussions with domain experts where specific business concepts and relations were tackled using precise Ubiquitous Language. But “distillation” of the deep model (to use Evans’ own terminology) certainly came from a developer trying out different competing models. We can imagine solutions like no Delivery value object (all logic in Cargo aggregate), Delivery as an aggregate in itself, etc.

Problem with Event Storming and Domain Events

In Event Storming related events and their corresponding commands are grouped together around placeholders representing future aggregates. But it is unclear how these aggregates are constituted and what is the nature of relationships between these aggregates.

How can one go from grouping of events/commands in Event Storming to design of aggregates?

Domain Events themselves are not a suitable starting point for domain analysis of a new system or a solution. Indeed, CustomerCreatedEvent or OrderDeletedEvent presuppose already existing demarcation of the domain space into Customer and Order aggregates which may or may not adequately represent a hidden “deep model” which can greatly facilitate problem solving involving customers and orders.

Here are some other difficulties inherently associated with Domain Events.

  • It is difficult to reason about a model where core business logic is spread around several (seemingly unrelated) event processors.
  • Event-centric architecture introduces asynchronous processing which is difficult to understand and to test.
  • Eventual Consistency is difficult to deal with correctly.


Brandolini’s Event Storming is a great technique to gather together all stake-holders in the organization and develop the Ubiquitous Language needed to analyse the problem space. It is also quite suitable tool for mapping out the existing system. However, one should not lose hold of the basic premise presented in the original work of Evans. Namely, that it is only through a thorough problem space analysis relying on the multitude of sources, that one can hope to stumble on a truly empowering insight — a “deep model”.

Developers must grasp the tenets of the underlying real-world phenomena they are trying to model. This understanding can come from discussion with a domain expert. And/or it can be achieved by informing oneself with the established rules and practices related to the problem. Only after several iterations a model starts to emerge where, with the help from careful aggregate design, the essence of the problem is dealt with using a precise, comprehensible, and relevant abstractions.

Aggregate or a group of aggregates should perform the the modification of the state under a close supervision of a specific use case. All this under a clear and testable guarantee that all the invariants proper to the system are being upheld, preferably — in a strongly consistent fashion. Of course, in the few cases, and especially when the changes to the state span different bounded contexts, a small number of integration events may need to be introduced. But, the use of domain events proper, should be delayed as long as possible, opting instead for a carefully designed aggregate structure and use cases.

Not understanding the strengths and weaknesses of techniques such as Event Storming and abundant peruse of the Domain Events pattern can be very distracting from, what Evans called “distillation” of the “core domain” and may mislead one from the path propitious to the discovery of a true “deep model”.


I have decided to write this little addendum to reiterate an important point. I am not dismissing Event Storming as a design technique. It definitively brings a lot of value to the table. The point of the article above was to issue a warning to DDD practitioners. There is a crucial moment when we pass from Event Storming proper to aggregate design in itself. This is actually a very difficult point which should not be underestimated.

There is an excellent article by Alex D, which delves precisely into the intricacies of this passage from Event Storming to aggregate design using a concrete example with a non-trivial domain. I strongly encourage my readers to consult the article by Alex. It will bring into the light the somewhat controversial point that I was trying to make by writing this post.


  1. “Event Storming, Black Magic or Real?”, article by Alex D