The Great Async/Await Debate: Why Go's Approach to Concurrency Might Be Better

BigGo Editorial Team
The Great Async/Await Debate: Why Go's Approach to Concurrency Might Be Better

The programming community is engaged in a heated debate about async/await, a feature that has become ubiquitous in modern programming languages. While initially celebrated as a solution to callback hell, the feature has sparked controversy among developers who argue that it creates more problems than it solves.

The Function Coloring Problem

One of the most significant criticisms of async/await is what's known as the function coloring problem. When a function uses await, it must be marked as async, and this requirement cascades up through the entire call stack. This infection of async markers has become a major pain point for developers, leading to widespread frustration and code complexity.

Alternative Approaches

Go's approach to concurrency has gained attention as a potential alternative. Instead of async/await, Go uses goroutines and channels, implementing what's known as Communicating Sequential Processes (CSP). This approach allows developers to write code that appears synchronous while the runtime handles the complexity of concurrent execution.

CSP is simpler. Simpler is easier to get right. I used to write a lot of asynchronous servers in C up until a couple of decades ago. I found it easy. Most people didn't. We have better ways of doing things today.

Key Approaches to Concurrency:

  • Async/Await: Stackless coroutines with explicit async markers
  • Go's Approach: Stackful coroutines with implicit concurrency
  • CSP: Communicating Sequential Processes
  • Virtual Threads: JVM's approach to lightweight threading

The Case for Stackful Coroutines

Many developers argue that stackful coroutines, as implemented in Go, provide better abstraction than the stackless variety used in most async/await implementations. The key difference lies in how the runtime handles execution context. Go's approach allows developers to write more straightforward code without explicitly marking async boundaries, while still maintaining efficient concurrent execution.

The UI Programming Challenge

One significant counterpoint in favor of async/await comes from UI programming. In GUI applications, blocking the main thread leads to unresponsive interfaces. Async/await provides a clean way to handle background operations while keeping the UI responsive. This has made it particularly valuable in frontend development and desktop applications.

The Performance Question

Recent developments, such as Java's virtual threads, have challenged the performance arguments traditionally used to justify async/await. Some developers argue that the complexity introduced by async/await isn't justified by its performance benefits, especially in typical business applications where context switching is rarely a bottleneck.

Conclusion

While async/await has become a standard feature in many modern programming languages, the debate around its merits continues. The discussion highlights a broader tension in software development between abstraction and complexity, and between different approaches to handling concurrent operations. As the field evolves, we may see new paradigms emerge that better balance these competing concerns.

Source Citations: Async Await Is The Worst Thing To Happen To Programming