Events vs. Commands in DDD
There are situations where events and commands seem to be a good solution for a problem. Where to use events and where are commands the best fit?
Differences between Events and Commands
Events represent a past, something that already happened and can’t be undone. Commands, on the other hand, represent a wish, an action in the future which can be rejected. An event has typically multiple consumers, but a command is addressed to only one.
Martin Fowler emphasizes in his talk the semantic difference between events and commands as a hint to understand the overall behavior by using the most natural terms for a particular business. In his point of view the question “events or commands” is a naming problem.
While this is true, it’s not the only one difference. I believe the key is responsibility and level of abstraction.
Consider a problem with two possible solutions, first using an event, second using a command:
With events Billing service subscribes to Sales service as a consumer, with commands Sales service actively uses Billing service. Events enable an independent choreography of services while commands create an orchestration where one or a few services control all others. This contradicts the definition of a service as a technical authority for a specific business capability. Sales and Billing are two separate business capabilities, which means Sales service should not include any payment considerations. On the other hand, it is fully Billing’s responsibility to deal with a newly placed order.
Commands as Infrastructure Messages
Commands are imperatives to a concrete action, typically the result of a user act. There’s usually no room for the called service to make any business decisions or reasoning about the action. Consider a common usage of a command:
MailServer makes no business decisions, it just sends an e-mail. On the other hand, sending an e-mail, SMS, or displaying a message on the screen is a business decision made by Sales service. MailServer is probably a separate component maintained by a different team or an external vendor. We can apply the same for the payment:
As already mentioned, we don’t want to make business decisions about payments in Sales service. We can stick with an event and wrap the payments into a separate service:
Now, we have two separate business services (Sales, Billing) and one technical service (PayPal), which is encapsulated in Billing service from the domain point of view. We can see PayPal service as part of Billing implementation and CollectPayment as an infrastructure message living outside of the domain.
We can reason about the MailServer similarly:
Domain service Customer Notification reacts on OrderPlaced event and sends SendEmail command to MailServer (an infrastructure service) to carry out its business decision of sending an e-mail to the customer.
Events and commands are not just two sides of the same coin. (Domain) events are part of the business domain and its ubiquitous language, while commands are a pure technical concern.
- Ask business to define the service boundaries.
- Use events for communication among domain services.
- Use commands only for communication with technical services.