Microservices Communication Patterns
Sync, async, and event-driven compared.
Microservices Communication Patterns
How microservices communicate with each other determines your system's reliability, latency, and coupling. Choosing between synchronous (HTTP/gRPC), asynchronous (messaging), and event-driven patterns is a fundamental architectural decision.
Synchronous Communication
REST over HTTP
// Service A calls Service B directly
var response = await httpClient.GetAsync("http://user-service/api/users/123");
var user = await response.Content.ReadFromJsonAsync<User>();Pros: Simple, well-understood, easy to debug.
Cons: Tight coupling, cascading failures, latency accumulates with each hop.
gRPC
// Protocol Buffers definition
service UserService {
rpc GetUser (UserRequest) returns (UserResponse);
}
// Client call
var user = await userClient.GetUserAsync(new UserRequest { Id = 123 });Pros: 2-10x faster than REST, strongly typed, streaming support.
Cons: Not browser-native, steeper learning curve, harder to debug.
Asynchronous Communication
Message Queues (Point-to-Point)
// Producer sends message to SQS
await sqsClient.SendMessageAsync(new SendMessageRequest {
QueueUrl = "https://sqs.../order-processing",
MessageBody = JsonSerializer.Serialize(order)
});
// Consumer processes independently
var messages = await sqsClient.ReceiveMessageAsync(...);Pros: Decoupled, reliable delivery, handles load spikes via buffering.
Cons: Eventually consistent, harder to trace, message ordering challenges.
Event Bus (Pub/Sub)
// Publisher emits event to SNS/EventBridge
await snsClient.PublishAsync(new PublishRequest {
TopicArn = "arn:aws:sns:...:order-events",
Message = JsonSerializer.Serialize(new OrderCreatedEvent { ... })
});
// Multiple subscribers independently process the event
// - Inventory service reduces stock
// - Email service sends confirmation
// - Analytics service tracks conversionPros: Loosely coupled, multiple consumers, event sourcing support.
Cons: Complex debugging, eventual consistency, event schema evolution.
Pattern Comparison
| Pattern | Coupling | Latency | Reliability | Complexity |
|---|---|---|---|---|
| REST | High | Low (per hop) | Medium | Low |
| gRPC | High | Very Low | Medium | Medium |
| Message Queue | Low | Higher | High | Medium |
| Event Bus | Very Low | Higher | High | High |
When to Use Each
- Synchronous (REST/gRPC): Query operations, real-time responses needed, simple request/response
- Message Queue (SQS): Task processing, work distribution, rate leveling
- Event Bus (SNS/EventBridge): Domain events, multiple consumers, audit trails
- Saga Pattern: Distributed transactions across services
Resilience Patterns
- Circuit Breaker — Stop calling a failing service after N failures, fail fast instead
- Retry with Backoff — Exponential backoff with jitter for transient failures
- Timeout — Set aggressive timeouts (2-5 seconds) to prevent cascading delays
- Bulkhead — Isolate connection pools per downstream service
- Dead Letter Queue — Capture failed messages for investigation and replay
Eazy SaaS Tip: We recommend starting with synchronous REST for simplicity, then introducing asynchronous patterns for specific use cases. The most common evolution: REST for queries, events for state changes. This hybrid approach gives you the simplicity of REST with the decoupling of events where it matters most.