Rust's async ecosystem fragmented around three runtimes. In 2026 Tokio dominates production. async-std faded; smol is a niche choice for embedded or library use. Understanding why helps you not pick the wrong one for a new project.

Advertisement

Tokio — the default

Multi-threaded work-stealing scheduler. Massive ecosystem (hyper, tonic, axum, sqlx all use it). Mature, well-documented, production-tested. The right answer for ~95% of new Rust async services.

async-std — historically

Designed to mirror std's API closely. Won mindshare 2019-2021. Lost steam as Tokio's ecosystem grew. Still maintained but new projects rarely choose it; library compatibility is harder.

Advertisement

smol — minimal and embeddable

Small footprint, single-threaded variant available. Right for: libraries that want to be runtime-agnostic, embedded systems, anywhere Tokio's size is a problem. The async-executor crate is its underlying primitive.

Runtime-agnostic libraries

If you're writing a library, target the futures-rs traits (Stream, AsyncRead, AsyncWrite) and let callers pick the runtime. Don't hard-depend on Tokio unless you really need it. Improves your library's reach.

When NOT async at all

CPU-bound work: use Rayon, not async. Simple multi-threaded server: regular threads + sync code may be simpler. Async is for I/O concurrency at scale. Don't async something that doesn't need it.

Tokio for production services. smol for libraries needing portability. Rayon for CPU-bound. Don't async sync workloads.