Messaging as a communication style: channels, brokers, commands versus events, and the pitfalls to avoid.
key idea / coordinatorservice / good pathin progress / watch outproblem / failureneutral
Asynchronous messaging
Messages travel over channels. A broker sits in the middle, buffers messages and hides service locations.
Commands usually use point-to-point. Events usually use publish-subscribe.
Brokers in depth
A broker holds messages until they can be delivered. How it groups consumers and counts retries decides how it behaves.
From Practical Event-Driven Microservices: at-least-once is arguably the most flexible choice. Failures are rare, so the performance hit is small, and duplicates cost little when handlers are idempotent.
Direct and indirect messaging in practice
Bootstrapping Microservices prefers the words direct and indirect to synchronous and asynchronous.
Bootstrapping Microservices uses a video-streaming service sending a "viewed" message to a history service.
Direct (HTTP)
Indirect (RabbitMQ)
Reply
Immediate success or failure
None to the sender
Coupling
Sender names the receiver
Sender does not know who listens
Receiver
Cannot ignore it
Handles it when ready
Best for
Commands needing an answer
Notifications and broadcasts
Cost
Tight coupling
Flow is harder to trace
With indirect messages no service is in charge. Behavior emerges from services reacting to messages. An unacknowledged message is not lost when a service crashes, because another replica handles it.
From Bootstrapping Microservices: plain DNS names are enough to target a service. Docker Compose uses the container name as the host name, so http://history/viewed works with no extra setup.
Durable or ephemeral broker, and the right to be forgotten
A broker either deletes a message once it is consumed (ephemeral, such as classic RabbitMQ queues) or keeps it in a log (durable, such as Kafka). Durable brokers make replay, new consumers and shared data streams possible. From Practical Event-Driven Microservices Architecture, ch. 3.
Ephemeral
Durable
Message after handling
Removed by the broker
Stays in the log
Best at
Point-to-point routing, fast short-lived messages
Streaming, replay, sharing data with many consumers
Weakness
Struggles when messages pile up, can hurt the whole cluster
Replication cost; erasure and security are harder
Right to be forgotten
Naturally satisfied
Needs a strategy such as crypto shredding
Only the services that handle sensitive data need this. It can also be done at infrastructure level with a sidecar that encrypts before publishing, so that each service does not implement it. Deleting an entity is normally just another event (a tombstone), but history should stay history, which is why the key approach matters.
Message types, patterns and events versus documents
Messages have a header (correlation id, message id, version or timestamp) and a body. The body is one of four kinds. Keep logic-driving flags out of headers. From Practical Event-Driven Microservices Architecture, ch. 3.
Events and documents both announce that an entity changed. Choose by what the consumer needs. From Practical Event-Driven Microservices Architecture, ch. 3.
Consumer situation
Prefer
Reacts only to one kind of change (update the invoice address)
Event
Needs most of the entity (notify the user with all order data)
Document
Needs the meaning or user intent for its logic
Event
Two fields changed together; you want one message
Document
New consumers must load the current state of everything
Document on a compacted topic
Default to events that capture user intent, then adapt to the consumers. Lesson 21 returns to event size.
Service topologies and common pitfalls
Not every service is event-driven. The book lists four shapes you will meet. From Practical Event-Driven Microservices Architecture, ch. 3.
Topology 1 suits simple, low-scale domains and gives immediate feedback. Topology 2 is a cheap way to bring an existing service into an event-driven system. Topology 3 is fully asynchronous but makes validation feedback hard to return. Topology 4, the process manager, reacts to events in one domain and sends a command to each affected aggregate, for example one per order after a user changes an address.
Pitfall
Why it hurts
Instead
Faking synchronous responses
Blocking until the change shows up breaks under load and times out.
Return 202 and expose status; accept eventual consistency.
Publishing one command to many services
A command targets one aggregate; others may even reject it.
One service owns the command; others react to its event.
Passive-aggressive events
An event that secretly asks another service to act is a hidden command.
Use a saga or process manager so the flow is visible.
Messaging gotchas
Scaling consumers must not break ordering, and duplicates will happen.
All events for one order go to one shard, so they are processed in order.
Messaging improves availability
Every synchronous hop multiplies the failure odds. Cut the hops.
Recap
Prefer asynchronous messaging through a broker for service-to-service calls.
Brokers give queues and topics, at-least-once delivery, and dead letter queues for poison messages.
Durable brokers allow replay but need a plan for erasure, for example crypto shredding.
Commands (imperative, one receiver) and events (facts, many receivers) are different. Documents carry full state. Queries are usually synchronous.
Avoid faking synchronous replies, multi-target commands and passive-aggressive events.
Quick check
The billing service must update the invoice address whenever the order address changes. Event or document?Show answer
An event (OrderAddressChanged). The consumer only cares about that change and the event keeps its meaning. A document would force billing to compare with stored state.
A user asks to be forgotten, but their events sit in a Kafka topic. What can you do?Show answer
If events were encrypted with a per-user key from a key store, destroy that key. The data in the log becomes unreadable without rewriting the log.
Why is publishing one CreateOrder command to inventory and notification services a smell?Show answer
A command targets one aggregate and can be rejected. Others should react to the OrderCreated event the order service publishes after it accepts the command.