compio: a completion-based Rust runtime that drops the mio abstraction
A thread-per-core async Rust runtime with IOCP/io_uring/polling.
At a glance
- What is it?
- compio is a thread-per-core async Rust runtime built on IOCP, io_uring and polling, inspired by monoio, and it is a set of twenty workspace crates rather than one library. It is fast in principle and awkward in practice today, because the project publishes no MSRV and most crates are pre-1.0 betas.
- Who is it for?
- Adopt compio when you are writing a new Linux or Windows workload where per-core locality and completion-based IO matter and you are willing to own the runtime, and take the crates individually through their subpaths rather than as a monolithic dependency. Do not adopt it for a service that depends on the wider Tokio ecosystem, because compio is explicitly not tokio-based and offers no drop-in compatibility layer.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 6, 2026, and from our analysis. They are not legal advice.
Star history
- compio-rs/compio1,944 ★ · +22
| Repository | 2026-10-16 | 2026-11-06 |
|---|---|---|
| compio-rs/compio | 1.9k | 1.9k |
22 Stars in the last 21 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Completion-based, not poll-based, and that is the architectural bet
compio describes itself as a thread-per-core Rust runtime with IOCP, io_uring and polling, inspired by monoio. The interesting word is thread-per-core. Rather than multiplexing many tasks onto a small pool of threads with a work-stealing scheduler, each core runs its own thread and its own set of tasks, which keeps scheduler state local and removes the cross-thread balancing cost.
The I/O model is completion-based. On Windows that means IOCP, on Linux io_uring, and polling as the fallback. The README is direct about why this matters: the runtime is not built on tokio, because tokio does not expose the APIs needed to control mio, and mio in turn does not expose the APIs needed to control IOCP. Reaching the native completion mechanism of each platform means owning that stack outright.
The name follows from the same idea. It comes from completion-based IO and follows what the README calls a non-existent convention that an async runtime should carry an io suffix.
The trade-off is honest and structural. Owning the stack is what gives you the high-level APIs for IOCP and io_uring, and it is also what stops existing tokio-based code from working unchanged.
Adding compio and running the first file read
The quick start is a cargo add with the features you intend to use:
cargo add compio --features macros,fsThe high-level APIs cover filesystem and network work, and the entry point is a `#[compio::main]` attribute on an async function. The example opens a file, reads it to the end at an offset, and asserts that the byte count matches the buffer length:
use compio::{fs::File, io::AsyncReadAtExt};
#[compio::main]
async fn main() {
let file = File::open("Cargo.toml").await.unwrap();
let (read, buffer) = file.read_to_end_at(Vec::with_capacity(1024), 0).await.unwrap();
assert_eq!(read, buffer.len());
let buffer = String::from_utf8(buffer).unwrap();
println!("{}", buffer);
}The `macros` feature is what provides the attribute, and `fs` pulls in the filesystem crate. That pattern of picking features rather than taking a default bundle is what you will use throughout, since the workspace is split into many small crates.
There is a lower entry point below the executor. The README notes you can drive the proactor, that is the completion driver without the async executor, manually, and points at the `driver` example for that.
Twenty workspace crates, most of them pre-1.0 and independently versioned
compio is not a single crate. Cargo.toml declares twenty workspace members: compio itself, plus compio-actor, compio-buf, compio-dispatcher, compio-driver, compio-fs, compio-io, compio-log, compio-macros, compio-net, compio-process, compio-quic, compio-runtime, compio-executor, compio-signal, compio-term, compio-tls, compio-ws and compio-compat, with resolver set to "3" and edition 2024.
The version numbers in the workspace dependencies are the interesting part. compio is at 0.20.0-beta.1, compio-driver and compio-fs and compio-net and compio-runtime are at 0.13.0-beta.1, compio-io at 0.11.0-beta.1, compio-tls at 0.11.0-beta.1 with default features off, compio-quic at 0.9.0-beta.1 with default features off, compio-actor at 0.2.0-beta.1, compio-executor at 0.2.0-beta.1, compio-dispatcher at 0.12.0-beta.1 and compio-buf at 0.9.0-beta.1. Only a few, such as compio-macros at 0.2.2, compio-signal at 0.10.1 and compio-term at 0.1.0, are outside the beta pattern.
That means every crate moves on its own cadence, and your dependency tree will contain a mix of beta numbers. Pin exact versions. A caret requirement across this many beta crates will pull in a surprise sooner or later.
No MSRV is stated, and the release line is still in beta
The README has a short section on Rust version that says more than it appears to. Compio does not have a minimum supported Rust version. The stated reason is that the project is not on a stable release rhythm yet, so any release may start using features from the latest stable Rust. The expectation set for users is that a recent stable toolchain is needed, and an MSRV may be declared once compio reaches 1.0.
In practice that is a CI problem more than a development problem. If your build pipeline pins a toolchain through rust-toolchain.toml, and the repository has one at its root for its own development, you should expect to track stable Rust more closely than you would with a 1.0 crate.
The release history supports the same reading. v0.19.1 shipped on 2026-06-14, v0.19.2 on 2026-08-18, and the latest is the pre-release v0.20.0-beta.1 on 2026-09-29, with the last push to the repository on 2026-10-14. A pre-release tagged on master means the 0.20 line is still settling, and the README's own statement that they might set an MSRV at 1.0 is the clearest signal about where the project sees itself.
tokio-console compatibility needs a cfg flag, and that tells you something
Observability is handled through the ecosystem's existing tooling rather than something built new. The `console` feature makes the runtime emit the tracing spans and events that tokio-console consumes, so a compio application can be inspected with the console tool: watch tasks, poll times and waker activity.
Setting it up takes two dependencies and a build flag:
cargo add compio --features console
cargo add console-subscriber# .cargo/config.toml
#
# `console-subscriber` refuses to run unless the runtime is known to be
# instrumented; this is the escape hatch it provides for runtimes other than
# tokio.
[build]
rustflags = ["--cfg", "console_without_tokio_unstable"]That cfg is worth pausing on. The console subscriber checks at runtime that it is attached to a known instrumented runtime, and refuses otherwise; `console_without_tokio_unstable` is the documented escape hatch for runtimes that are not tokio. This documented escape hatch exists for runtimes other than tokio.
The example that demonstrates it runs an echo server on a dispatcher, so the console shows a thread-per-core application's tasks spread across worker threads alongside deliberately misbehaving tasks. It sets the flag on the command line instead of the config file:
RUSTFLAGS="--cfg console_without_tokio_unstable" \
cargo run --example console --features console,time,net,dispatcher,syncThe console module documentation describes what is reported and, just as importantly, what is not, which is where the honest limits of this integration are written down.
How compio differs from tokio, monoio and glommio
The README compares compio against the alternatives, and the comparisons are specific rather than flattering.
Against tokio, the objection is architectural. Tokio is described as a good general-purpose async runtime, but it is poll-based, and on Windows it uses undocumented APIs. The project wants high-level APIs over IOCP and io_uring, and states plainly that tokio does not expose the APIs needed to control mio while mio does not expose the APIs needed to control IOCP. That is why compio is not tokio-based, and it is a technical reason rather than a preference.
Against monoio, the difference is platform reach. Monoio focuses on Linux and io_uring and falls back to mio elsewhere, so on Windows it gives up the completion model.
Against glommio, the difference is simply Windows: glommio does not support it, while IOCP is the model compio is built around.
The catch-all claim is the one to treat carefully. The README says most other runtimes are, at the moment compio was created, either poll-based, use io_uring in a way the project links to as unsound, or are not cross-platform. That is a point-in-time statement, and a runtime released since then may not fit any of those three buckets.
Where compio is the wrong choice
The clearest wrong-tool case is dependency compatibility. Because compio is not tokio-based and provides no compatibility shim, any crate built on tokio is unavailable to you. compio-compat exists in the workspace, but the README does not describe what it bridges, and its presence should not be read as a general tokio bridge.
The second case is production conservatism. Most crates are pre-release betas with independent version numbers, the project has no MSRV, and the current release tag is itself a beta. For a service where a runtime bug is an outage, that is a large amount of your risk budget to hand to a project at this stage.
The third case is workloads that are not I/O bound at the per-core level. The entire premise is that per-core locality plus completion-based I/O beats a work-stealing scheduler. If your work is CPU bound, or if you are porting existing async code and want to change nothing but the runtime, the trade does not pay.
What compio does offer is the chance to own the I/O stack on Linux and Windows with the same source, which is a real gap, just a narrow one.
Editorial conclusion
Adopt compio when you are writing a new Linux or Windows workload where per-core locality and completion-based IO matter and you are willing to own the runtime, and take the crates individually through their subpaths rather than as a monolithic dependency. Do not adopt it for a service that depends on the wider Tokio ecosystem, because compio is explicitly not tokio-based and offers no drop-in compatibility layer. Before starting, pin exact crate versions: most are beta releases on independent cadences, the project states there is no minimum supported Rust version, and any release may require the latest stable toolchain.
Frequently asked questions
How do I add compio to a Rust project and read a file?
Run `cargo add compio --features macros,fs`, then use `#[compio::main]` on an async main and `compio::fs::File` with the `AsyncReadAtExt` trait, as shown in the README quick start. The macros feature provides the attribute and fs provides the filesystem API.
What is the minimum supported Rust version for compio?
There is none. The README states compio does not have an MSRV because it is not on a stable release rhythm, so any release may use features from the latest stable Rust, and users should expect to need a recent stable toolchain. An MSRV may be set once compio reaches 1.0.
Is compio built on tokio?
No. The README explains that tokio does not expose the APIs needed to control mio, and mio does not expose the APIs needed to control IOCP, so compio implements its own completion-based stack over IOCP on Windows, io_uring on Linux and polling as a fallback.
Can I inspect a compio application with tokio-console?
Yes, with a build flag. Enable the `console` feature and add console-subscriber, then set `rustflags = ["--cfg", "console_without_tokio_unstable"]`, which is the escape hatch console-subscriber provides for runtimes other than tokio. The console module docs describe what is and is not reported.
Is compio stable enough for production?
Most workspace crates are on beta versions such as 0.20.0-beta.1 for compio itself and 0.13.0-beta.1 for compio-fs, compio-net, compio-driver and compio-runtime, and the project states it is not on a stable release rhythm. Pin exact versions rather than caret ranges.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/compio-rs-compio)Star history chart for your README
[](https://hysenlabs.com/projects/compio-rs-compio)Was this useful?