A four year plan for async Rust

Async/await in Rust remains deeply polarizing: some developers praise it for enabling highly concurrent, efficient network services, while others find it ergonomically awkward, “viral” across codebases, and poorly suited to embedded or simpler use cases. Commenters react to a proposed four‑year roadmap for Rust async, debating missing pieces like async in traits, generators, a standard `block_on`, runtime‑agnostic traits, and whether std should ship a default executor. Underneath the technical points is a broader tension between Rust’s systems‑programming roots and its growing use for web and service backends, as well as frustration with the slow, conservative pace of stabilizing major language features.

Async “contagion” and workarounds

  • Many complain that if a dependency is async, “everything must be async.”
  • Others counter that you can isolate async by:
    • Spinning up a small runtime (e.g., Tokio single-threaded, smol, pollster) and using block_on.
    • Running async code on a dedicated thread and communicating via channels.
  • Critics respond that this still drags in heavy runtimes and extra dependencies, which matters for build times, trust, and constrained environments.

Ergonomics, complexity, and real-world experience

  • Some find async Rust a major wart: viral, unintuitive, lifetime-heavy, poor compiler errors, difficult closures, awkward async_trait interactions.
  • Others report years of smooth use in large production codebases, arguing complaints are exaggerated and often come from limited or outdated experience.
  • There’s fatigue over recurring “async is hard/bad” arguments that ignore nuances of the design or the linked article.

Domains: servers vs embedded and systems

  • For high-concurrency network services (HTTP servers, DB-heavy proxies), many say async is indispensable for predictable performance and scalability.
  • For embedded and low-level systems, there’s a split:
    • Some avoid async entirely (favoring RTOSs, actors, threads, interrupts, DMA, event loops).
    • Others praise frameworks like Embassy as a lightweight RTOS replacement and ergonomic task structuring.

Runtimes, Tokio dominance, and stdlib

  • Tokio has effectively “won” the ecosystem; many crates hard-depend on it (locks, channels, spawn).
  • Some see this as a cultural and architectural problem and want runtime-agnostic traits (AsyncRead/Write, Stream, spawn, locks, channels) in std.
  • Proposals include:
    • A minimal executor or block_on in std (possibly pollster-like).
    • Not making Tokio the default runtime; both Rust and Tokio maintainers reportedly oppose that.

Concurrency models: threads, async, green threads

  • Debates over whether async should be a language feature vs library/tooling problem.
  • Some argue thread-per-connection is good enough for most workloads and simpler; async mainly helps with huge numbers of concurrent IO-bound tasks.
  • Others argue green threads / fibers (Go-style goroutines, Java Loom) give better DX than colored async, without infecting APIs.
  • Counterpoint: Rust previously removed green threads; reintroducing them with Rust’s safety model and embeddability constraints is non-trivial.

Language design gaps and plans

  • Pain points mentioned: Pin/Unpin complexity, lack of async generators/iterators, weak async-in-traits story (improving soon), missing async closures ergonomics, no async drop, lack of linear/unforgettable types.
  • Some want a Move trait and immovable-by-default semantics to simplify async; others are cautious.
  • Generators are seen as closely related to async and desirable, but their real-world payoff is debated.

Rust evolution pace and governance

  • Some criticize “glacial” stabilization (e.g., block_on in std, generators, deeper async fixes), wanting 6‑month timelines instead of multi-year plans.
  • Others defend slow, conservative stabilization because features are effectively forever and must be right before freezing.