Ian Wold

Book Club 6&7/2025: Async

27 September 2025 3 Minutes History Patterns Standards Architecture Distribution

Not the keyword, but asynchronous communication. It just seemed that 'Async' as a title was more interesting.

hero

These last two months, the interesting thing that I'm researching is asynchronous communication patterns. Last year I wrote a whole series on the Fallacies of Distributed Computing exploring some common dos and don'ts for systems that rely on network communication. Asynchronous communication (which, I'm just going to type "async" here on out) is a common solution to reach for as the number of nodes in the distributed network increases. It solves the problem of huge latency in requests that need to chain through several services, though at the expense of system complexity and comprehension.

In an ideal world, systems would be quite "flat", with user-level requests being able to be serviced in only a single network call to the server. Plenty of systems can't accommodate this for one reason or another, a backend might need to consult other services to fulfill a request; here though, plenty of systems can be designed so that those bottom-level services don't need to make blocking calls to each other to fulfill their own requirements. Commonly, there might be a backend-for-fronend that owns all of the synchronous calls, making it easier to manage temporal dependencies by isolating them all to a particular area.

Suppose the lower-level services do need to exchange data? Alternately, suppose we end up with too many temporal dependencies, resulting in long-running calls even though we've made them architecturally understandable within a single layer? That's where we should be inclined to reach for async. I'm supposing here that we're imagining a relatively well-designed system; that the call patterns are well-considered to fulfill actual business needs.

How does async work? At the top level, when transformations happen to any data or state in the system, the service doing the changing emits an event through a shared bus, which is then read by systems that care about that transformation. Those systems will store their own representations of the data they care about, and are free to service requests on the "hot path" without having to introduce blocking calls. This has several implications: data is duplicated in many points throughout the system, the data is eventually consistent, the code for each service becomes more complex, considerations need to be made to prevent data drift, and plenty more there.

Given the set of problems solved by async and the implications of adopting it, there are many patterns and ideas around them. I haven't been terribly organized or disciplined in this research; this is a grab-bag of things that have caught my eye these last two months:

Kind of related:

Watching:

This has all taken me down a rabbit hole about AsyncAPI, but that may be for another time...