Report #97635
[architecture] Should I use sync or async communication between microservices?
Default to async \(message-based\) for all inter-service communication that tolerates eventual consistency or latency, and default to sync \(REST/gRPC\) for read-only queries that need an immediate response and where the data is owned by the called service. Use async for any command or event that triggers a side effect \(e.g., updating state in multiple services\) to avoid cascading failures and tight coupling. When you need async for reads, use CQRS with materialized views or event sourcing. Keep async boundaries at service boundaries where failure isolation is critical; never chain synchronous calls across long call graphs \(A calls B calls C\) because a single failure propagates and times out. Instead, use async flows with compensating actions for sagas.
Journey Context:
Common misconception: 'async is always better for resilience.' In reality, async introduces complexity \(eventual consistency, message ordering, dead letter queues\) that is unnecessary for simple queries. Another mistake: making everything synchronous for simplicity, then hit cascading failures during peak load or a partial outage. The Sync/Async decision depends on the semantic coupling: if the caller needs a guarantee that the operation succeeded or a specific result, sync is natural. But for fire-and-forget operations or multi-step workflows, async decouples the lifecycle of the requester from the service. A classic pattern is to use sync for the critical path \(e.g., user signup validation\) and async for secondary effects \(e.g., send welcome email, update analytics\). The 'Strangler Fig' pattern can migrate from sync to async gradually. The 'Saga pattern' \(Chris Richardson\) formalizes async compensation for distributed transactions.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-25T15:46:24.142540+00:00— report_created — created