async-channel
Async multi-producer multi-consumer channel for Rust with bounded and unbounded variants.
Repository Health
Technical Analysis
async-channel is a Rust crate providing an asynchronous multi-producer multi-consumer (MPMC) channel, where every message sent is received by exactly one of the existing consumers. It offers both bounded channels with a fixed capacity and unbounded channels that grow as needed, with senders and receivers that can be freely cloned and shared across tasks.
Part of the smol-rs async ecosystem, the crate integrates with any async runtime through futures-based send and receive operations, supports Stream and Sink-style usage, and works in no_std environments. With hundreds of millions of downloads it is one of the most widely used channel primitives in async Rust.
What You Get
- Bounded and unbounded async MPMC channels via bounded() and unbounded()
- Cloneable Sender and Receiver halves that can be shared across many tasks
- Async send/recv futures plus non-blocking try_send and try_recv
- Stream and Sink integration for use with the futures ecosystem
- no_std support and runtime-agnostic operation across async executors
Common Use Cases
- Distributing work items across a pool of async worker tasks
- Passing messages between concurrent tasks without blocking threads
- Building backpressure-aware pipelines with bounded capacity
- Fanning out jobs where each message should be handled once
Under The Hood
Architecture - The whole crate lives in a single ~1,400-line src/lib.rs. Internally it wraps a lock-free concurrent-queue for message storage and uses event-listener-strategy to park and wake tasks waiting to send (on a full bounded queue) or receive (on an empty one). A shared inner channel struct tracks sender and receiver counts so the channel closes automatically when either side is fully dropped; Sender and Receiver are thin cloneable handles over this shared state, with pin-project-lite driving the Send/Recv future state machines and futures-core providing Stream.
Tech Stack - Rust 2021 (MSRV 1.60) with a lean dependency set: concurrent-queue for the buffer, event-listener-strategy for async wakeups, futures-core for the Stream trait, and pin-project-lite for safe pin projection. Optional portable-atomic and portable-atomic-util dependencies plus a no-default std feature enable no_std and constrained-platform builds; dev-dependencies include futures-lite and wasm-bindgen-test for testing, including on wasm targets.
Code Quality - As a foundational smol-rs crate the code is carefully written and well documented, with dedicated integration tests for bounded and unbounded behavior (tests/bounded.rs, tests/unbounded.rs) covering capacity, closing, and concurrency, plus a maintained CHANGELOG and CI. It is mature and stable, receiving periodic correctness and dependency updates rather than large feature churn.
API Design - The public API is small and idiomatic: bounded(cap) or unbounded() return a (Sender, Receiver) pair; you await sender.send(msg) and receiver.recv(), or use try_send/try_recv for non-blocking paths, and iterate the receiver as a Stream. Cloning either half to add producers or consumers is trivial, and the runtime-agnostic future-based design means it drops into any executor with no setup, keeping the learning curve low for anyone familiar with channels.