Async await: the worst thing to happen to programming?
Async/await is praised as a major simplification for I/O-heavy and UI code, but many programmers argue it introduces “function coloring” — a viral split between async and sync code that complicates APIs, refactoring, and composition. Commenters contrast stackless async/await with goroutines, green threads, and effect systems, debate whether async semantics are really different from cooperative multithreading, and note that alternatives like CSP, actors, or virtual threads may offer clearer models. Overall, the trade-off is framed as ergonomics and mental overhead versus explicitness and performance in concurrent programming.
Scope of the Debate
- Two main threads:
- Is async/await a good concurrency model vs threads, goroutines, actors, etc.
- Is async/await’s syntax and “function coloring” design a problem.
Why Async/await Exists
- Designed to handle large amounts of I/O without exhausting OS threads.
- Blocking on many OS threads (e.g., thousands to millions of sleeping connections) is seen as impractical in some environments; green threads/event loops mitigate this.
- Particularly valued in server code and UI frameworks where blocking the main thread is unacceptable.
Function Coloring & “Infectious” Async
- Many comments focus on “async is viral”:
- Once a function awaits, it must be marked async; callers must often do the same up the call stack.
- Bridging async and sync code (especially in Python, JS, C#) is awkward and error‑prone.
- Some see this as analogous to an IO monad “polluting” code, but at least making side effects explicit.
- Others argue this “infection” is inherent to expensive/IO operations and that making it explicit in the type system is a feature, not a bug.
Comparisons to Other Models
- Goroutines / stackful coroutines:
- Seen by several as conceptually “just threads with cheaper scheduling,” blocking semantics, and no function coloring.
- Argued to be easier to teach and use in large apps, though some find Go’s concurrency still “low level.”
- CSP, actors, green threads, virtual threads:
- Suggested as cleaner ways to express concurrency, especially for large systems.
- Some believe these models scale better conceptually; others note they demand more background in formal methods.
- Generators, callbacks, and promises:
- Async/await widely regarded as a big improvement over callback “pyramid of doom.”
- Some prefer promise/future APIs or event-loop abstractions without new keywords.
Language- and API-Specific Friction
- C#: legacy sync codebases and synchronization context semantics are pain points, though many find async/await easy for typical IO/DB-heavy apps.
- JavaScript:
- Event-loop model makes sync blocking APIs and sleep impractical on the main thread.
- Complaints about async-only Web Crypto forcing async “all the way down.”
- Python:
- Async/await separation (e.g.,
asyncio.runvs running in a loop) makes composition tricky.
- Async/await separation (e.g.,
Meta and Tone
- Several comments call the “worst thing to happen to programming” framing exaggerated or clickbait.
- Overall split:
- Strong approval from those who value explicit, ergonomic async I/O.
- Strong criticism from those who dislike function coloring, ecosystem churn, and compositional limitations.