Microservices Communication Patterns That Hold Up
When to call synchronously or message asynchronously, and how sagas, the outbox and circuit breakers keep services reliable.

Choose microservices communication patterns that hold up: sync or async by need, sagas for consistency, a transactional outbox and idempotent consumers.
Splitting an application into services is the easy part. The hard part is how those services talk to each other. Choose badly and you get a distributed system with all the coupling of a monolith plus network failures: one slow service stalls five others, an order is charged but never shipped, and nobody can trace a request end to end. Microservices communication patterns are the established ways services exchange requests, events and data, along with the techniques that keep that exchange reliable. This guide explains synchronous and asynchronous communication, when to use each, how to keep data consistent across services with sagas and the transactional outbox, and how to make failures survivable and visible.
Microservices communication patterns: sync or async
Every interaction between services is broadly one of two kinds:
- Synchronous request and response: one service calls another, usually over HTTP or gRPC, and waits for the answer. Simple to understand and debug, but the caller depends on the callee being available and fast at that moment.
- Asynchronous messaging: a service publishes a message or event to a broker, and other services process it when they can. The publisher does not wait, and consumers can be offline briefly without losing work, but the flow is harder to follow and results arrive later.
Neither is better in general. A good rule is to use synchronous calls when the caller genuinely needs an answer now to continue, such as checking a price before showing it, and asynchronous messaging when the work can happen afterwards, such as sending a confirmation or updating a search index.
Commands, events and queries
It helps to name what each message is:
- Commands ask a specific service to do something: "reserve stock for order 123". There is one intended handler.
- Events announce that something happened: "order 123 was placed". Any number of services may react, and the publisher does not need to know who they are.
- Queries ask for data and expect a response.
Events reduce coupling, because new consumers can be added without changing the publisher. Commands make responsibility explicit. Mixing them up, such as publishing an "event" that really expects one specific service to act, produces confusing systems.
Keep data consistent across services with sagas
In a monolith, placing an order, reserving stock and charging a card can happen in one database transaction. Across services with their own databases, there is no single transaction. The saga pattern, described on microservices.io, handles this as a sequence of local transactions, one per service. If a later step fails, earlier steps are undone by compensating transactions, such as releasing reserved stock.
The same page describes two ways to coordinate a saga:
- Choreography: each local transaction publishes events that trigger the next step in other services
- Orchestration: an orchestrator tells each participant which local transaction to run
Choreography suits short flows with few participants. Orchestration is easier to understand and change when flows are longer, because the sequence lives in one place.
Publish events reliably with the transactional outbox
A common bug: a service updates its database, then publishes an event, and crashes in between. The database says the order exists, but no other service ever hears about it. The transactional outbox pattern solves this by writing the event to an outbox table in the same database transaction as the business change. A separate relay then reads the outbox and publishes the events.
The same page notes that the relay might publish a message more than once, for example if it crashes after publishing but before recording that it did. Consumers therefore need to be idempotent, typically by tracking the IDs of messages they have already processed. Since message brokers can also deliver more than once, idempotent consumers are good practice in any case.
Make synchronous calls survivable
Where services call each other synchronously, protect against slow and failing dependencies:
- Timeouts on every call, chosen for the caller's needs
- Limited retries with increasing delays, only for operations safe to repeat
- Circuit breakers, as described in Martin Fowler's article, which stop calling a failing service for a period and fail fast instead
- Fallbacks, such as cached data, where a degraded answer is better than none
Avoid long chains of synchronous calls. If one request passes through five services in sequence, its availability is limited by all five, and its latency is their sum.
Worked example: an order flow across four services
The table below shows a hypothetical order flow using a mix of patterns. Services and steps are illustrative.
StepFromToPatternWhyShow price and stockWeb front endCatalogue serviceSynchronous query with timeout and cache fallbackCustomer needs an answer nowPlace orderWeb front endOrder serviceSynchronous command; order saved as pendingCustomer needs confirmation the order was receivedOrder placedOrder serviceBrokerEvent via transactional outboxMust not be lost if the service crashesReserve stockOrchestrator in order serviceInventory serviceAsynchronous command; compensation releases stockPart of an orchestrated sagaTake paymentOrchestratorPayment serviceAsynchronous command; compensation refundsSaga step that can failOrder confirmedOrder serviceBrokerEvent via outboxEmail, analytics and search update independently
If payment fails, the orchestrator sends a compensating command to release stock and marks the order as failed, and the customer is told to retry payment.
Make the system observable
Distributed flows are hard to debug without help. Give every request and message a correlation ID that is passed along and logged by each service, use distributed tracing to follow requests across services, and monitor queue depths and consumer lag. A saga that stalls halfway should be visible on a dashboard, not discovered by a customer. Messages that fail repeatedly should move to a dead letter queue with the error recorded, so they can be inspected and replayed once the cause is fixed rather than blocking the queue behind them.
If you are still deciding whether to split into services at all, our guide to microservices versus modular monolith compares the options, and our guide to event-driven ERP shows event patterns applied to business systems.
Common mistakes in service communication
- Long chains of synchronous calls between services
- Publishing events outside the database transaction
- Consumers that are not idempotent
- No compensating actions for multi-step flows
- No timeouts or circuit breakers on service calls
- No correlation IDs, so requests cannot be traced
Frequently Asked Questions
What are microservices communication patterns?
They are established ways for services to exchange requests, events and data, such as synchronous request and response, asynchronous messaging, sagas and the transactional outbox.
When should services communicate asynchronously?
When the caller does not need an immediate answer to continue, such as sending notifications or updating other systems after an order. Asynchronous messaging tolerates brief outages.
What is the saga pattern?
A way to keep data consistent across services as a sequence of local transactions, with compensating transactions undoing earlier steps if a later one fails.
Why use a transactional outbox?
It writes events in the same database transaction as the business change, so an event is never lost if the service crashes before publishing it.
Design service communication that holds up
We design and build microservice communication with reliable messaging, sagas and observability. See our custom app development services, or talk to us about your architecture.
About the Author
Manav Sharma is the founder of Insyrge and a CRM solutions architect. He works across Zoho, Salesforce, HubSpot, Odoo and more, designing the CRM setups, integrations and automations that keep sales and operations teams working from the same data.
Need Help Implementing This in Your Business?
Our certified Zoho consultants and automation experts can help you design and deploy custom workflows tailored to your operations.
Book Free Consultation