Introduction
How microservices communicate with each other determines the coupling, reliability, and performance of the entire system. This article analyzes communication patterns and guides on choosing the right pattern for each use case.

1. Synchronous Communication
1.1 Request-Reply Pattern
┌──────────┐ HTTP/gRPC ┌──────────┐
│ Order │ ──────────────►│ Product │
│ Service │◄────────────── │ Service │
└──────────┘ Response └──────────┘
Order Service gọi Product Service để validate product trước khi tạo order.
Phải đợi response → coupling tạm thời (temporal coupling).
Advantages:
- Simple, easy to understand, easy to debug
- Response immediately
- Explicit error handling (HTTP status codes)
Disadvantages:
- Temporal coupling: caller blocked until receiving response
- Cascade failure: if Product Service goes down → Order Service also fails
- Latency increases with each hop in the call chain
1.2 Minimize Sync risks
- Circuit Breaker: breaks circuit when downstream service fails
- Timeout: set a reasonable timeout (not too long)
- Retry with backoff: retry with exponential backoff
- Fallback: returns cached data or default response
- Bulkhead: isolate connection pools for each downstream
2. Asynchronous Communication
2.1 Message Queue Pattern
┌──────────┐ Enqueue ┌──────────┐ Dequeue ┌──────────┐
│ Order │ ──────────────►│ Queue │──────────────►│ Email │
│ Service │ │(RabbitMQ)│ │ Service │
└──────────┘ └──────────┘ └──────────┘
Fire-and-forget: Order Service gửi message, không đợi.
Email Service xử lý khi sẵn sàng (rate riêng).
Queue đảm bảo message không mất.
Use cases:
- Task distribution (send email, resize image)
- Work queues (process video, generate report)
- Load leveling (absorb traffic spikes)
2.2 Event Streaming / Pub-Sub Pattern
┌──────────┐ ┌──────────────┐
│ Order │──publish──────►│ Kafka │
│ Service │ OrderPlaced │ Topic: │
└──────────┘ │ orders │
└──┬───┬───┬───┘
│ │ │
┌──────────┘ │ └──────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Payment │ │Inventory │ │ Email │
│ Service │ │ Service │ │ Service │
└──────────┘ └──────────┘ └──────────┘
1 event → N consumers. Services không biết nhau → loose coupling.
Events được lưu trữ → có thể replay (event sourcing).
Use cases:
- Domain events (OrderPlaced, PaymentConfirmed)
- Data replication across services
- Event sourcing & audit trail
- Real-time analytics
2.3 Event Notification vs Event-Carried State Transfer
| Pattern | What does Event contain | What do consumers need |
|---|---|---|
| Event Notification | ID only: {orderId: "123"} | Query source service again |
| Event-Carried State | Full data: {orderId, items, total, ...} | No need to query again |
Recommendation: Event-Carried State Transfer helps reduce coupling (consumers do not need to call the source again).
3. Compare Message Brokers
| Features | RabbitMQ | Apache Kafka | NATS |
|---|---|---|---|
| Model | Message Queue | Event Stream/Log | Pub/Sub + JetStream |
| Ordering | Per queue | Per partition | Per subject |
| Retention | Consumed → deleted | Configurable (days/forever) | JetStream: configurable |
| Throughput | ~50K msg/s | ~1M msg/s | ~10M msg/s |
| Replay | No | Yes (offset-based) | JetStream: Yes |
| Consumer groups | Yes | Yes | JetStream: Yes |
| Complexity | Average | High (ZooKeeper/KRaft) | Low |
| Best for | Task queues, RPC | Event streaming, sourcing | Cloud-native, lightweight |
3.1 When to use what?
RabbitMQ: Task queues (send email, process image)
Request-Reply pattern (RPC over messages)
Complex routing (exchanges, bindings)
Kafka: Domain events (OrderPlaced, PaymentConfirmed)
Event sourcing & CQRS
Data pipeline & streaming analytics
Audit trail (event log)
NATS: Lightweight microservices communication
Real-time messaging (chat, notifications)
Cloud-native, Kubernetes-native
Request-Reply + Pub/Sub combined
4. Hybrid Approach (Production Pattern)
In practice, most systems use a combination of both:
┌─────────────────────────────────────────────────┐
│ E-Commerce Communication │
├─────────────────────────────────────────────────┤
│ SYNCHRONOUS (REST/gRPC): │
│ • GET product details (query, cần response ngay)│
│ • Validate payment (command, cần kết quả) │
│ • Search products (query, real-time) │
├─────────────────────────────────────────────────┤
│ ASYNCHRONOUS (Kafka Events): │
│ • OrderPlaced → trigger Payment, Inventory │
│ • PaymentConfirmed → trigger Shipping │
│ • UserRegistered → trigger Welcome Email │
│ • ProductUpdated → update Search Index │
└─────────────────────────────────────────────────┘
Summary
| Pattern | When to use | Tradeoff |
|---|---|---|
| Sync (REST/gRPC) | Need immediate response, query data | Tight coupling, cascade failure |
| Async Queue | Task distribution, load leveling | Eventual consistency |
| Async Events | Domain events, data sync | Complexity, difficult debugging |
| Hybrid | Production recommendation | Need to manage both |
Next article: Lesson 7: Database per Service & Polyglot Persistence