Distributed Services can't exist without Eventual Consistency.
Network communication is far from perfect. And distributed systems inevitably face eventual consistency due to network delays and communication failures.
Thank you to our sponsors who keep this newsletter free:
Multiplayer auto-documents your system, from the high-level logical architecture down to the individual components, APIs, dependencies, and environments. Perfect for teams looking to streamline system design and documentation management without the manual overhead.
Let’s talk about three patterns that deal with eventual consistency, illustrated with practical examples.
Imagine you have two services:
Orders
Invoices
When the customer places an order, you must generate the associated invoice.
1. Background Synchronization Pattern
You save the Order and then update/create the invoice in the background.
The job in schedule checks for new or changed orders and creates or updates invoices.
This approach decouples the services and reduces the latency on the user-facing service (Orders service).
You get Eventual Consistency but slowly since the background job runs on a specific schedule.
2. Orchestrated Request-Based Pattern
You save the Order and send it to the Invoices service to generate the invoice right away.
It requires some Orchestrator Service, which can be a separate or existing service.
Unlike the previous pattern, this one attempts to process the entire distributed transaction.
But, once we are involved in any kind of distributed transaction, we need to talk about compensating transactions. If something fails, compensating transactions are executed to revert the changes.
3. Event-Based Pattern
Event-Based is more advanced, requires more infrastructure, and, of course, more observability.
Services emit events, and others listen to them to update their data.
In this case, you save the Order and emit an event of "order-created."
The Invoices service listens to these events and creates a new invoice based on the Order.
The services do not need to know about each other and can scale independently.
TL;DR
Background Synchronization offers simplicity and decouples services but introduces delays in data consistency.
Orchestrated Request-Response offers a controlled flow with reliability but increases response times.
Event-based brings loose coupling and scalability and allows services to react to changes at the cost of complexity.
Eventual Consistency is the price for better performance, scalability, and availability.
System Design Classroom is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.
Articles I enjoyed this week
7 Techniques for Database Performance & Scaling by
How Netflix Uses Chaos Engineering to Create Resilience Systems by
Optimising Docker Builds: Leveraging Build Cache for Efficient Development by
Thank you for reading System Design Classroom. If you like this post, Share it with your friends!
Solid post Raul!
One can only imagine how many problems it will create to have the whole thing done synchronously with chained calls. After deciding to move to a distributed architecture, it's better to embrace eventual consistency.
Thanks for the mention as well!
Great stuff, well structured.