Why command should not call command in CQRS?

Eric De Carufel
Workleap
Published in
4 min readMar 22, 2023

A brief CQRS introduction

In software development, CQRS (Command Query Responsibility Segregation) is a pattern that separates the responsibility for read and write operations in a system. In this pattern, commands are responsible for changing the state of the system, while queries are responsible for returning data without changing the state of the system.

To call or not to call, that is the question

A common question that arises in the context of CQRS is whether a command can call another command. While technically possible, this can introduce potential problems such as re-entrance, where a command calls another command and gets called back again, creating an infinite loop. This is because calling a command is done through the mediator, and there are no direct connections between the commands themselves.

The mediator problem

In the mediator pattern, commands and queries are handled by separate handlers that are registered with a mediator. When a command is dispatched, the mediator uses its internal logic to locate the correct handler and pass the command to it for execution. This means that the commands and handlers do not have direct knowledge of each other, which can make it difficult to identify when one command is calling another.

When a command handler receives a command, it is responsible for performing the necessary logic to execute the command and potentially make changes to the system. If that logic involves calling another command, there is no way for the mediator to know that this has happened, as it only knows about the initial command that was dispatched. This can introduce potential problems, such as the aforementioned issue of re-entrance, where a command calls another command that in turn calls the original command again, creating an infinite loop.

Possible solution

To avoid such problems, it is generally recommended to keep commands self-contained and not have them call other commands directly. Instead, if there is a need for multiple commands to be executed together, a higher-level command or workflow can be created to orchestrate the execution of the individual commands.

The CQRS call stack

The CQRS call stack is an important aspect to consider when designing a system that follows this pattern. It is important to understand the guidelines for where to put your code to avoid potential problems and ensure a well-designed system. The call stack includes the following layers:

  • API Controller: Translate HTTP calls into object and dispatch the processing to the next layers.
  • Commands: Objects which names are Domain Specific and are used to package all information needed to perform an operation.
  • Query: Objects which names are Domain Specific and are used to package all parameters needed to perform a request to a storage source.
  • Services and Repositories: These are the most basic building blocks. These blocks will translate Domain Language into Technical Language and bridge the gap between the domain and all other dependencies.

As you go down the call stack, the code becomes more reusable, and as you go up, the code becomes more specific. It is important to balance these two factors when deciding where to put your code. While it may be acceptable to have some code duplication in the top layers, as you go down the call stack, the code should become more generic and reusable.

Conclusion

In conclusion, while it is technically possible for a command to call another command in CQRS, it is generally not recommended. The mediator pattern used in CQRS makes it difficult to identify when one command is calling another, which can introduce potential problems such as re-entrance. To avoid these problems, it is best to keep commands self-contained and use a higher-level command or workflow to orchestrate the execution of multiple commands if necessary.

--

--