Async Communications - Patterns & Anti-Patterns
Async Communications - Patterns & Anti-Patterns
Another most common example is majority of UI frameworks. Here, all user clicks are first dispatched through a controller which
in turn call backs respective application. The call back from UI controller to back-ends are usually asynchronous if they involve
heavy processing.
Another good example of asynchronous programming (as a pure design pattern) is Active Object. An active object is one which
has it's own private thread such that one can keep many requests in a queue and execute one-by-one.
When a given object needs to return the API, while working in the background to actually accomplish the work, the usual
methodology is to have a multi-threaded system to achieve this.
But this concept goes beyond threads or objects inside an application to become asynchronous. One of the best usage is in
Distributed systems where two applications doesn't necessarily need to wait for each other for co-ordinations.
Patterns:
Any asynchronous communication essentially follows any of these patterns to
achieve what’s promised.
1. Choreographed Asynchronous Events
2. Orchestrated, Asynchronous & Sequential
Choreographed Asynchronous Events:
1. All services listen to a central event bus & awaits an event. Triggering the
downstream event is a responsibility that each service owns.
2. A Notification component may expect an event to trigger an email or SMS.
3. Decentralized workflow management.
Pros: Scales well for a write-heavy system.
Cons: Synchronous reads needs mediation & workflow is spread through the
system.
Eg: AWS SNS
Orchestrated, Asynchronous & Sequential:
1. Each Service is a producer & consumer to the central bus. Responsibility of
orchestrator involve routing messages to their corresponding services.
2. Each Component consumes an incoming message & produces the response
back on the message queue. Orchestrator consumes the response & does
transformation before routing.
Eg: RMQ, kafka
Hybrid Approach:
Combining Orchestrated & Choreographed mechanisms.
Orchestrated- Dictates the Workflow
Choreographed - Executes the workflow by learning the consumers themselves
However, there are ways to counterfeit these trade offs. Some of them are:
Sync-Wrapper:
Where the request reaches the server & waits until a response is received.
Although, the server performs async calls downstream.
CQRS:
Architectural style that separates reads from writes. Good fit for systems with heavy
reads & writes.
Data from write database streams to a read database. Queries run on a read-
optimized database.
A system like this is far more complex in structure but it scales better. Moreover, the
components can remain stateless
Anti -Patterns
(bad practices)
1. Dependent Events
2. Sequential Events - Sabotages the actual purpose of Async interaction.
3. Events with expectations - will lead to coupling
4. Generic Event- cannot clarify the intent & can create issues.
5. Leaky Events- Events should be a abstraction that represents a business
process, should not include internal implementation.
6. Entity-Based event- Events reflecting relational DB model lacks clarity.
7. Event as command- publishing in message bus to request that something
has happened in another service, command instead of a domain event.
8. Event as Method calls- Too many events can end up in chatty integration,
increasing the burden on the downstream.