Advanced · Distribute
Choose REST or Messaging by Coupling
Compare immediate replies, workflow latency, fan-out, ordering, and failure ownership.
Primary source: Spring Cloud 2024 Reference Documentation
Lesson 4 of 4
1d streakThe Architectural Question
Synchronous calls fit decisions needing an answer now; events fit facts consumed independently—mixing the two couples workflows that should evolve separately.
What this guide proves
- Use synchronous calls when the current decision requires an immediate answer
- Use events for facts consumed independently
- Version contracts additively and test consumers
Temporal Coupling and the Cascading Failure Math
When microservices communicate synchronously over HTTP (REST), they become temporally coupled: Service A cannot finish its request until Service B responds, which in turn waits on Service C. If any service in the chain slows down or fails, the entire transaction fails.
The availability of a synchronous chain is the mathematical product of the availabilities of all individual services:
Composite Availability = A1 * A2 * A3 * A4
If 4 microservices each have 99.5% availability:
Composite Availability = 0.995^4 = 98.01% availability!
(More than 7 hours of unplanned downtime per month!)Temporal Coupling Cascades Outages
Request-Reply vs Event-Carried State Transfer (ECST)
To achieve true autonomous decoupling, services transition from synchronous Request-Reply queries to Event-Carried State Transfer (ECST). Instead of Order Service querying Customer Service over REST on every single checkout request, Order Service consumes CustomerUpdated Kafka events and maintains its own local read model.
If Customer Service goes offline for maintenance, Order Service continues processing orders seamlessly with zero downtime!
The Architectural Decision Framework: REST vs Messaging
Use this decision matrix when choosing communication protocols in enterprise architectures:
| Architectural Requirement | Synchronous REST (RestClient) | Asynchronous Messaging (Kafka/RabbitMQ) |
|---|---|---|
| Immediate Response Required by User | Yes (e.g. query catalog, authenticate) | No |
| Heavy Side-Effects / Notifications | No (causes latency spikes) | Yes (process in background workers) |
| Cross-Service Consistency | Requires tight coupling | Eventual consistency via Transactional Outbox |
| Temporal Decoupling | Low (both services must be online) | High (producer publishes even if consumer is down) |
| Throughput & Buffering | Limited by thread pool capacity | High (Kafka buffers millions of spikes smoothly) |
Operational Trade-off Verification Checkpoints
Evaluate system resilience when downstream dependencies are offline:
# 1. Stop downstream Notification Service container
docker stop notification-service
# 2. Place order in Order Service (using asynchronous messaging)
curl -i -X POST http://localhost:8080/api/orders -d '{"orderId":"ORD-99"}'
# EXPECTED: HTTP/1.1 201 Created (Order placed successfully; event buffered in Kafka!)
# 3. Start Notification Service container
docker start notification-service
# Notification service boots up, reads buffered Kafka event, and sends receipt email with zero data loss!Active Recall Checkpoint
Why does Event-Carried State Transfer (ECST) increase service availability during network partitions?
Hint: Differentiate between synchronous remote RPC calls and localized queries.
Show answer & explanation
By caching necessary foreign entity data in a local read model populated via events, the service can execute queries locally without making synchronous network calls to external microservices that might be offline.
Runtime Architecture & Flow
Decision canvas
Evaluate the choice across three constraints
These are comparison criteria, not sequential steps. A strong answer states which constraint dominates in the current system.
Use synchronous calls when the current decision requires an immediate answer
Ask how each option changes this guarantee, its operational cost, and its failure mode.
Use events for facts consumed independently
Ask how each option changes this guarantee, its operational cost, and its failure mode.
Version contracts additively and test consumers
Ask how each option changes this guarantee, its operational cost, and its failure mode.
Decision prompt: Model payment authorization as a command and order-created as an event.
Working Implementation
Code Walkthrough
Model payment authorization as a command and order-created as an event.
package com.example.arch;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class RestVsMessagingLab {
// Event-Carried State Transfer (ECST): local read model populated by Kafka events
private final Map<String, CustomerSnapshot> customerReadModel = new ConcurrentHashMap<>();
public record CustomerSnapshot(String customerId, String name, String tier, int creditLimit) {}
// Consumed from Kafka event; preserves local read model so service stays up if CustomerService dies
public void onCustomerUpdated(CustomerSnapshot snapshot) {
customerReadModel.put(snapshot.customerId(), snapshot);
}
// Zero network hops during order placement; immune to customer service downtime!
public Optional<CustomerSnapshot> getCustomerLocal(String customerId) {
return Optional.ofNullable(customerReadModel.get(customerId));
}
}Synthesis & Production Verification
Production Acceptance Criteria
- Classify each interaction as a command or a fact before choosing transport
- Publish events that carry facts, not requests awaiting replies
- Evolve one contract additively and prove consumers still pass
Key Takeaway
Synchronous REST couples services temporally and multiplies failure rates, whereas asynchronous messaging and Event-Carried State Transfer preserve availability during outages.
Architectural & Technical Review
Core Interview Questions
Q01How does temporal coupling in synchronous REST chains degrade composite system availability?Show answer
The availability of a synchronous chain is the mathematical product of the availabilities of all services in the chain (A = A1 * A2 * A3). A failure or latency spike in any downstream dependency immediately cascades upstream.
Q02What is Event-Carried State Transfer (ECST) and how does it insulate services from partner downtime?Show answer
In ECST, consumers subscribe to domain events and cache foreign data in a local read model. The consumer queries its local database rather than calling the producer service over HTTP, staying online even if the producer is down.
Q03What is the decision framework for choosing synchronous REST versus asynchronous messaging?Show answer
Use synchronous REST when the caller requires an immediate computed response (e.g. user authentication, search queries). Use asynchronous messaging for heavy side effects, notifications, and event-driven data synchronization.
Production Pitfalls
Critical Anti-Patterns
- Pitfall: Building deep synchronous REST request chains across multiple microservices — Causes latency accumulation, thread pool exhaustion, and cascading cluster outages when one service degrades.
- Pitfall: Using asynchronous messaging for interactive user queries requiring immediate responses — Forces complex polling or WebSocket coordination where a simple REST query would be simpler and faster.
Module Certification Quiz
Prove Module Mastery
Comprehensive question set covering all lessons in this module.
Primary Documentation & Specifications
Lesson Primary References
Supplementary Module Resources