Key points
- The core problem: In any language with
async/await, functions are effectively tagged 'red' (async) or 'blue' (sync). Rules force red callers, red tests, red frameworks. Bob Nystrom's 2015 essay "What Color is Your Function?" formalized this. Coloring is essentially irreversible: changing one I/O function red paints half the project. - Hidden cost #1 — Sequential syntax hides parallelism:
await get_orders(); await get_recommendations()looks naturally sequential even when both depend only onuserand could run in parallel viaasyncio.gatherorPromise.all. - Hidden cost #2 — Runtime coloring: In Rust, the standard library has no built-in async runtime; Tokio, async-std, and smol are mutually incompatible. The ecosystem split adds an extra axis of complexity beyond function signatures.
- Alternative path A — Java Project Loom (JDK 21, 2023): No async/await at all. Developers keep writing
Thread.start()/Thread.join(); the JVM virtualizes threads underneath so millions can coexist without OS thread overhead. No coloring, noasync-compatshims. Java's earlier pain withFuture(1999–2012) arguably made this conservatism easier. - Alternative path B — Zig (PR merged 2025-07-08): Rather than a workaround, Zig removed
async/awaitkeywords. I/O is abstracted as an interface (io) passed in like an allocator; the caller decides whether the underlying mechanism is blocking, threaded, or event-loop-driven. Functions themselves do not change color. - Comparison of three routes:
- Practical guidance: Use async only when there is real I/O concurrency to gain; check whether adjacent
awaits have a true ordering dependency (and parallelize if not); isolate coloring using thread pools orasyncio.to_threadrather than letting it propagate everywhere. - Historical context: Promise concepts appeared in Friedman & Wise (1976, Indiana) and futures in Baker & Hewitt (1977, MIT). They slept in academia for 22 years until Kegel's C10K problem made event-driven servers necessary — and callbacks unbearable — creating the niche async/await filled.
- Bob Nystrom, "What Color is Your Function?" (2015) — http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/
- Dan Kegel, "The C10K Problem" (1999) — http://kegel.com/c10k.html
- Java Project Loom, JDK 21 virtual threads (2023)
- Zig, "remove async and await keywords" PR (2025-07-08)
| Approach | Representative | Core strategy | Trade-off | |---|---|---|---| | async/await | Python, JS, Rust, C# | Sync syntax for async code | Function coloring, ecosystem fragmentation, hidden serial dependencies | | Virtual threads | Java Loom | Sync code, virtualized scheduler | JVM complexity, not universal | | I/O interface | Zig | Scheduling passed as parameter | Design still being validated, learning curve |