Event-Driven Message Types and Messaging Patterns
This article covers
- Message Types(Command , Query , Event , Document)
- Difference between Event and Document
- When to use Documents over Events
- Messaging Patterns (Send/Receive , Publish/Subscribe , Request/Response)
- Resource and more detail
Messages are usually composed of a header and a body. We can use the header to pass additional information common to all messages, much like HTTP headers. A typical example is the correlation id.
The message body has the full information we want to publish. Messages can be commands, events, or documents. Queries are also a common concept, and typically, they aren’t a message but a common concept in event-driven architectures.
Message Types
there are 4 message types :Command ,event, document, query
notice:queries are not message in essence but in world of event driven they usually consider as message.
let’s go in detail what are these message types
Commands
are orders to perform a given action. We should name them with a verb in the imperative form, for example, CreateOrderCommand. A command is a request to a given service to perform an action and thus can be rejected or fail a validation. We can change aggregates by sending a command to perform a given action in that aggregate and often reflect a user’s action. Typically, commands affect one service and a specific domain; they usually aren’t published to several subscribers, only one. Although often commands are messages, a command can also be an HTTP request if the service receives changes through an API instead of a message broker. commands are related to a single system.
Events
notify something that has changed in a given domain or aggregate. They are named in the past participle verb and inform that something has happened, for example, OrderCreatedEvent. They are facts and, unlike commands, aren’t liable to be rejected; they are something that already happened. Events are the most common block of event-driven architectures and are used to pass information and signal relevant changes throughout the architecture’s components. They are often published to several consumers and can accommodate new consumers in the future, unlike commands that are related to a single system.
Documents
are much like events; the service publishes them when a given aggregate or entity changes, but they contain all the entity’s information, unlike events which typically only have the information related to the change that originated the event. Although they often are triggered by changes in the aggregate, they often don’t give information about what change triggered the document, unless we specifically add it to the document. If someone changed an order address, the generated event could be OrderAddressChanged and contain the information about the new order’s address. The same change could trigger a document, for example, OrderDocument, which would have all the order information; each receiver would have to interpret it in the way that made sense to that service.
Queries
are requests of information issued to a given system to obtain the service’s data. Typically, they aren’t messages and are often synchronous requests like an HTTP request. They also don’t change state; they simply request information.
Bellow illustrates an example of an interaction between these entities.

A user placing an order would query the product’s stock to the inventory service and then trigger a CreateOrderCommand by submitting an order that would be consumed by the order service. Once the service creates the entity, it publishes a CreateOrderEvent and an OrderDocument which are consumed by the inventory service and the notification service, respectively.
When to Use Documents over Events
we discussed we could use either events or documents to notify changes in entities. Choosing to publish an event or a document can be debatable, and they often accomplish the same goal. However, they are fundamentally different, and we should use them in specific use cases.
In this subsection, we will discuss several topics that will help us decide where to use documents or events.
Events represent a specific change and have domain value by themselves since they represent something the user did or a change in the domain.
Documents just inform the entity’s latest state, so they lose the domain value carried by the event’s meaning.
If the receiving system needs to react only to changes in the address, it is more beneficial to use the event. For example, if a billing service had to update the address in the invoice, whenever the user changes the order’s address, it would be easier to handle the OrderAddressChange. Using the OrderDocument would need to save the orders internally after each event or request the order from the order service to understand the address had changed.
However, documents often simplify consumers that need more information from the entity than an event would make available. For example, if we need to notify the user with all the order information every time an order changes, we would benefit from using the document. It would prevent the service to request or store the additional information that wasn’t available in the event to send the notification; this would greatly simplify the consumer. With partial events, it also becomes complex to maintain all the entity’s data. For example, if the order entity would grow and have more and more properties, it would probably imply that we needed to create more and more partial events. If the consumer needs to maintain all the order data, it is more complex to handle several different events than one with all the information.
Another advantage of using documents is that if the user changed the address and quantity simultaneously, that would mean two different partial events. In contrast, if we use the document, we only need to publish one.
Overall, it becomes simpler to use documents when we need a large part of the entity’s data. However, we lose the meaning and the inherent change behind the event; if the consumer needs that meaning to process its logic, it will have to infer the meaning internally. In those cases, we are better off using partial events. It is often more useful to use events that reflect the user’s intent, and this should be our go-to approach.
But we always need to have the event consumer’s needs in mind and adapt accordingly. In some use cases like we mentioned before, documents are useful;
Messaging Patterns
Event-driven architectures are composed of services that publish events to event brokers. Other services react to those events to accomplish their business rules. The services are built to be horizontally scalable, and several instances of the same service can consume from the same queue, having the load distributed between all of them.
bellow figure illustrate Typical messaging patterns used in an event base (event-driven) architecture

Send/Receive Pattern:
Commands are typically send/receive
The interaction between the UI and the order service is a send/receive pattern. Typically, commands are requests to change a given entity or aggregate information and have a very specific receiver. The request to change the data is only relevant for the order service; no other service needs or should receive that command. Send/receive is typically, a point-to-point communication between two services with a specific purpose, often a request to do a given action on that service.
It is essential to distinguish the publication pattern along with the types of events.. Commands often have a very specific purpose and have a close relation with the domain they are changing; it is important to guarantee only the desired service reacts to the command.
Publish/Subscribe Pattern:
Events are typically publish/subscribe
The interaction between the order service and the inventory and notification service is a publish/subscribe pattern. The order service publishes changes that happened in its domain, and interested services subscribe to those changes and process them. As the previous pattern, typically they are fire-and-forget; the originating service only guarantees that the message was published to the broker.
Multiple services can handle the events and will process them at different rates. Each service might have several instances, and each instance will receive various events and process them at different rates in parallel. This is the basis of horizontal scalability, which also introduces complex challenges on how to handle the concurrency between the several instances, out-of-order events, and eventual consistency associated with it, which we will discuss further in this book.
Request/Response Pattern:
The interaction between the UI and the order service is intrinsically asynchronous due to happening through a message queue. The UI also doesn’t know when the changes took place. The UI can notify the user the changes took place by handling the corresponding event. Once the service handles the command and applies the changes, it will publish an event signaling those changes. The command and the event can be correlated by an id which can be used by the UI to understand that the requested changes were applied. This way, the UI can be a publisher of commands and a receiver of events, implementing the request/response pattern. The changes can be linked together by a correlation id that would be published in the command and transmitted in the event.

The UI implements both send/receive and request/response patterns. It sends a command which is received by the order service and handles the event generated by that command. The publish/subscribe pattern is implemented by the inventory and notification service by handling the events published by the order service.
Resource and more detail:
Practical Event-Driven Microservices Architecture by Hugo Filipe Oliveira Rocha — Apress