In the context of a DDD application following CQRS and the event sourcing pattern, I have 2 questions.

  1. At which layer should the direct calls to the Infrastructure layer be made? At the Application layer (ie. direct inside command/query handlers) or at the Domain Model layer (abstracted inside models behavior)?
  2. At which layer should events be published and consumed (considering the ES pattern)?

I'm learning DDD and all the patterns usually used around it and in this specific context I found conflicting information.

2 Answers 2


In CQRS/ES should database calls be done in command handlers or domain models?

Not an easy question to answer with authority.

Historically, CQRS comes from domain driven design (if you go back far enough, you'll find that the CQRS pattern was part of a collection of ideas labeled "distributed domain driven design".)

Therefore, for the most part, you'll find that CQRS/ES answers this question the same way that DDD does.

At the time that Eric Evans was writing his 2003 book, "best practice" emphasized layered architectures. A given layer could have dependencies on the layers below it, but not on the layers above it. So if you review chapter 4 ("Isolating the Domain") you'll see that there are some lines drawn directly from the domain layer to the infrastructure layer -- for instance domain code interacting directly with the "unit of work" infrastructure.

Subsequent to the publishing of Eric's book, ideas like "Hexagonal Architecture" (Cockburn, 2005) and "Onion Architecture" (Palermo, 2008) rose in popularity, re-organizing the directions of the permitted dependencies. In these styles, you are more likely to see domain layers with "no" external dependencies, rather than having the occasional infrastructure dependency.

The common practice that I see in CQRS today follows something close to these newer styles - the domain model is directly concerned with representations of information in local memory only, and concerns like I/O (which includes the load/store of information from the durable store) are addressed in the application code.

ES doesn't really change this - events are just another kind of data model that we might use to keep track of information. Copying those events from the domain model to our durable object stores is still something that is coordinated by the application code (just as it would be if we were storing "current state"), and the publishing of events after storage likewise is controlled by application code.


They aren't really that incompatible. We have these two principles:

  • CQRS says that the business logic is enforced inside the command
  • DDD says that your domain model handles the business logic

So to keep both happy, you have your Command Handler work with your domain model. And to keep it Event Sourced, the only thing that needs to be altered is how you store changes to the model.

In short the answer is "yes". The Command handler invokes your domain model which enforces the business logic.

Where you may have a slight disconnect in this thinking is in how you work with the data. It's best to think of the events as facts you are storing, which when played back will provide a fully constituted model.

The layer which handles storing changes will be working with the discrete facts (events) that describe what happened. When you retrieve that data, you can use a Projection to reconstitute your domain model.

In Domain Driven Design, you typically separate infrastructure from the domain model using interfaces. For example, you have the concept of a "Repository", and that interface is part of the domain, but the implementation uses your infrastructure.

The idea is that it is less important how the state is stored and more important how to find the domain models to perform work on. So the Repository implementation is free to change the type of data storage you use (database, flat files in a blob store, graph, etc.) because those are implementation details. The core business functionality is still in the domain model.

This leads to easier mocking in your system since you only have to mock the repository, rather than deal with the minutia of how to prep data.

Distinction between Event Sourced and Event Driven:

  • Event Sourced means you use your events as the stored state of your model
  • Event Driven means you send messages to invoke commands

This distinction can be lost because both use "events". One team I know of that adopted event sourcing changed the name "events" to "facts" to help the team think about it properly.

An event in Event Sourced is typically a past tense fact or record. For example:

  • UpdatedCart
  • PurchasedCart
  • StockReserved

The contrast with Event Driven is that the events are typically present tense commands for other services to react to. They are very different things. Examples of event driven names:

  • DeductAccount
  • ReserveStock
  • NotifyCustomer

There are more than one way to work with event sourcing. For example, you can publish the past tense event on a topic queue so that anyone listening can react to that fact and update their environments. Or, those other services can query for updates to the entities they care about.

You can use both Event Sourcing and Event Driving together, but it can be very confusing if you don't disambiguate your terminology like the team I referred to above.

  • Thanks for the answer but it's still not clear to me. When you say "The Command handler invokes your domain model which enforces the business logic" are you saying the direct calls do Infrastructure should be made inside the domain models? What about the publishing and consuming of events in an ES context? Commented Jul 15, 2021 at 11:34
  • DDD has several concepts to separate infrastructure and domain models. For example, the Repository Pattern, and your Repository handles storing the events. Commented Jul 15, 2021 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.