Tokio: enable the full feature set, and mind the five crates and five changelogs
GitHub describes it as A runtime for writing reliable asynchronous applications with Rust. Provides I/O, networking, scheduling, timers, .... The repository metadata lists Rust as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- Tokio is the asynchronous runtime for Rust, described as event-driven and non-blocking, and it is three components: a multithreaded work-stealing scheduler, a reactor over the operating system's event queue, and asynchronous TCP and UDP sockets. Its README is short, and the details an adopter needs are elsewhere: a feature flag list behind a page, a minimum supported Rust version with a published history, five crates each with its own changelog, and a repository that includes a stress test, a file descriptor prewarm example and a spelling dictionary.
- Who is it for?
- Use Tokio if you are writing networked or concurrent Rust and you want a runtime with a work-stealing scheduler and async sockets rather than one thread per connection. Do not treat the README's dependency line as a production configuration, because it asks you to enable every feature flag, which is a teaching default rather than a choice.
- 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 12, 2026, and from our analysis. They are not legal advice.
Star history
- tokio-rs/tokio33,675 ★ · +744
| Repository | 2026-08-13 | 2026-11-12 |
|---|---|---|
| tokio-rs/tokio | 32.9k | 33.7k |
744 Stars in the last 91 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Three components, and one of them is the operating system
The overview names the parts, and the list is short enough to be the architecture.
There is a multithreaded, work-stealing task scheduler. There is a reactor backed by the operating system's event queue, with the specific queue named as one of three depending on platform. And there are asynchronous TCP and UDP sockets.
The middle one is where the portability lives. A reactor over an event queue means the runtime's behaviour on Linux, on the BSD-derived systems, and on Windows is the same code path over three different kernel interfaces, and the README is explicit that those are the mechanisms. That is also the part that carries the platform risk, because each queue has its own edge cases and a runtime that wraps three of them is three sets of edge cases.
The scheduler is described as work-stealing, which is a specific claim: idle threads take work from busy ones rather than being parked. For an application whose tasks are unevenly distributed that matters, and for one that is not it is invisible.
Above that list sit three adjectives, and only one of them is measurable. Zero-cost abstractions and bare-metal performance are performance claims the README does not quantify, while the reliability claim is structural: it comes from Rust's ownership, type system and concurrency model rather than from the runtime.
The example tells you to enable every feature flag
The example section starts with an instruction before any code: make sure you enable the full features of the crate on the manifest, and then gives the line.
[dependencies]
tokio = { version = "1.53.1", features = ["full"] }The version in that line matches the newest release tag, so the example is kept current. The feature set is the part to think about, because a runtime's flags gate whole subsystems, and enabling all of them is the right default for a first run and the wrong one for a production dependency you did not write.
The README acknowledges this indirectly. After the example it says that to see a list of the available feature flags that can be enabled, there is a documentation page for them. So the enumeration exists; it is just not in the file.
That is the shape of the whole README: a correct minimal starting point, and a set of links for everything an adopter actually needs to decide. Nothing here is wrong, but nothing here is a configuration either.
The example spawns a task per connection, and the snippet stops mid-expression
The code in the README is a TCP echo server, and the shape of it is the lesson.
use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;Three things to notice. The entry point is an ordinary function marked with an attribute macro, so there is no explicit runtime construction and no manual executor. The listener is bound to the loopback address on a high port, so the example is a development binding and will not accept a remote connection. And the accept loop spawns a task per accepted socket, moving the socket into the async block, with a one kilobyte buffer per connection and a match on the read that returns when the peer closes.
The snippet in the file stops partway through that match, which is a fair warning: the readme is an illustration and the example directory is the reference. That directory holds twenty named programs, including one for graceful shutdown and one for a custom executor, which are the two things a real service needs and a tutorial usually skips.
Five crates, five changelogs, and one version number that is not the whole story
The changelog section opens with a sentence that is easy to miss and important for anyone pinning: the repository contains multiple crates and each crate has its own changelog.
Five are listed. The runtime itself, a utility crate, a streams crate, a macros crate and a testing crate. So the tag you see in the release list describes the runtime, and nothing in it tells you which version of the other four your build resolved.
The workspace manifest makes the arrangement explicit. Those five are members, and beneath them are the internal ones: benchmarks, examples, a stress test, a build test suite and an integration test suite. And there is a patch section that points each of the five crates at its own directory in the repository, which is how a workspace containing the published crates builds them locally rather than resolving them from the registry.
The practical consequence is that upgrading the runtime is one decision and upgrading its utility crate is another. A changelog link per crate is the mechanism the project gives you for telling them apart, and it is worth using before you bump the runtime.
The minimum Rust version has a six-month floor and a published history
The supported Rust versions section is the most precisely written part of the README, and it reads as a policy rather than a note.
The runtime keeps a rolling minimum supported version policy of at least six months, and when the minimum is increased the new Rust version must itself have been released at least six months ago. The current minimum is 1.85. And the minimum is not raised automatically; it happens only as part of a minor release.
Then there is a history, mapping minor version ranges to the Rust version each supported. Everything from 1.54 onwards is on 1.85, with earlier ranges stepping down through several Rust versions. It is published in the readme rather than in a changelog, which means you can see how far back the current floor reaches and judge how expensive it is to be on an old toolchain.
The caveat at the end is the part to plan around. The project says it tries to avoid a situation where a dependency raises the minimum version transitively, and then says outright that this is not guaranteed. That caveat describes your lockfile precisely, and it is the reason to commit one.
The configuration names every internal flag the runtime uses
The workspace manifest ends with a lints block that looks like housekeeping and is actually a map of the crate.
It is a lint against unexpected configuration values, paired with an explicit list of the custom configuration flags the project considers legitimate. There is one for fuzzing, one for running the concurrency tests, one for a polling fallback in the underlying I/O library, one for allowing a particular blocking descriptor, one for internal multi-threaded counters, one for a locking primitive substitution, one for disabling the tuning tests, one for unstable features, and a check on the operating system value that includes a Windows variant.
So that one block names the test modes the project runs, the escape hatches it keeps, and the platform-specific configuration it cares about, in a form the compiler will warn about if you get a name wrong. That is a better failure mode than a silently ignored configuration value, and it is the kind of detail that distinguishes a runtime with a large test matrix from one without.
It also tells you something about the shape of the project: there is a fuzzing mode and a concurrency-testing mode, which means the correctness story depends on tooling you will not see in the readme.
Named pipes, a descriptor prewarm, and a spelling dictionary
The rest of the tree is a list of what the project worries about.
There are directories for benchmarks, for a stress test, for build tests and for integration tests, and a dependency policy file that checks what the crate is allowed to depend on. There is a cross-compilation configuration. There is a spell checker with its own configuration and a custom dictionary, which is what a project with three kernel families and a dozen internal names does about documentation drift.
The examples are the clearest index of the platform concerns. There are three named-pipe programs, which is Windows interprocess communication. There is a program that prewarms the file descriptor table. There is one for graceful shutdown, one for a custom executor, and one that prints each packet as it arrives.
Taken together, those filenames are a list of the failure modes this runtime has been made to survive, and they are a better guide to what to test in your own service than the three adjectives at the top of the file.
Editorial conclusion
Use Tokio if you are writing networked or concurrent Rust and you want a runtime with a work-stealing scheduler and async sockets rather than one thread per connection. Do not treat the README's dependency line as a production configuration, because it asks you to enable every feature flag, which is a teaching default rather than a choice. Before you pin: read the feature flag page and enable only what you use, because a runtime's features pull in platform-specific code; pin the lockfile rather than the crate, since the project states plainly that a dependency may raise your effective minimum Rust version; and remember that the five crates in the repository version independently, each with its own changelog.
Frequently asked questions
how to use tokio
Add the crate to your manifest with the full feature set, mark the entry point as an async function with the runtime attribute macro, and then use its types. The README's example binds a TCP listener on the loopback address, accepts in a loop, and spawns a task per connection. For anything beyond that it points to a guides site, the API documentation, a chat server, and a discussions page.
how to install tokio
The README gives a manifest line rather than a package manager command: add the dependency with the version and the full feature set, for example a version matching the newest release tag with the full feature enabled. It also links a documentation page listing the available feature flags, since the readme asks you to enable all of them without enumerating them.
how to use tokio rust
It is the runtime for writing asynchronous applications in Rust, MIT licensed, providing three components: a multithreaded work-stealing task scheduler, a reactor over the operating system's event queue, and asynchronous TCP and UDP sockets. The project also maintains a family of libraries around it, including a web framework, an HTTP implementation, a gRPC implementation, a component library, a tracing framework and a low-level I/O abstraction.
how to use tokio spawn
The README's echo server spawns a task per accepted connection with the spawn call, moving the socket into the async block, giving each connection its own buffer, and returning when the read reports the peer has closed. The example directory holds twenty further programs, including one for graceful shutdown and one using a custom executor.
Official sources
Where developers are discussing it
Posts on Hacker News, dev.to and Lobsters that link to this repository, found by our scan of those communities. 1 in the last 30 days; newest first.
- Renting Out One T4 to Three Customers: Gemma 4, vLLM Multi-LoRA and a Rust Gatewaydev.to · Oct 16, 2026 · 2 points · 0 comments
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/tokio-rs-tokio)Star history chart for your README
[](https://hysenlabs.com/projects/tokio-rs-tokio)Was this useful?