Events, commands and queries

2 min read
On trails:EDAstep 2/8

Every message between services is one of three kinds, and the kind decides how it is named, who receives it and what the sender may expect. An event states something that already happened, a command asks one service to do something, and a query asks one service for data.

KindNamed asGoes toCan the receiver refuse?Example
EventPast tenseZero, one or many subscribersNo, it already happenedOrderPlaced
CommandImperativeOne ownerYes, it can fail or be rejectedReserveStock
QueryA questionOne ownerIt can return nothing or an errorGetOrderStatus

Events

An event is a fact. PaymentReceived cannot be refused by the services that hear it, because the payment has already been received. The producer does not expect any particular reaction, and there can be many subscribers or none. Microsoft’s guide puts it as a message “that a producer raises to announce that something happened”, with no expectation of a specific action.

Commands

A command asks for work: ReserveStock. It goes to the one service that owns that work, and the owner can reject it, for example because the stock is not there. The sender may wait for the outcome and decide what to do next. Commands have stricter delivery needs than events, because a lost command can fail the whole business transaction, and processing one twice can cause a double charge.

Queries

A query changes nothing. It asks for data and expects an answer, so it normally travels over a direct request, such as a call to an APIRESTful API designNaming, methods, status codes, formats and security for an API that is easy to use.Opens in a new tab, not over a broker. Whether to query another service at all is covered in asking another service for dataAsking another service for dataFour ways to get data a service does not own, and what each costs.Opens in a new tab.

The catch

A command dressed as an event hides a dependency. If Orders publishes OrderPlaced but the design only works when Payments charges the card, Orders is relying on a specific service to act. Martin Fowler calls this a “passive-aggressive command”. When the sender needs a specific service to act, send a command to that service and name it as one. Publish an event only when the producer would be correct whether or not anyone reacts.


Sources