---
title: "The Tokio Upgrade from 0.2 to 1.x"
description: "Fly.io’s Rust-based load balancer handles almost all of its traffic and stands on Tokio and Hyper, motivating an upgrade from Tokio 0.2 to 1.0. The team waited to upgrade until related crates including hyper, reqwest, async-compression, tokio-io-timeout, tokio-tungstenite, and sentry were ready; after a few weeks, most of the ecosystem had upgraded. The migration foregoes Tokio’s Stream implementations pending stabilization in the standard library, relaxes mutable-access requirements, changes AsyncRead and AsyncWrite polling to return Result<()>, and requires more explicit pinning for !Unpin futures. Because runtime::Handle lacked block_on, the team worked around the restriction with Arc; standard TcpListener values also required set_nonblocking(true) before TcpListener::from_std. Other changes included renamed APIs and revised Hyper WebSocket upgrades, and the author says the major upgrade was not hard."
---

# The Tokio Upgrade from 0.2 to 1.x

[Fly.io](https://yomu.fyi/company/fly-io) · Feb 12, 2021

**Type:** Tutorial

## Summary

Fly.io’s Rust-based load balancer handles almost all of its traffic and stands on Tokio and Hyper, motivating an upgrade from Tokio 0.2 to 1.0. The team waited to upgrade until related crates including hyper, reqwest, async-compression, tokio-io-timeout, tokio-tungstenite, and sentry were ready; after a few weeks, most of the ecosystem had upgraded. The migration foregoes Tokio’s Stream implementations pending stabilization in the standard library, relaxes mutable-access requirements, changes AsyncRead and AsyncWrite polling to return Result<()>, and requires more explicit pinning for !Unpin futures. Because runtime::Handle lacked block\_on, the team worked around the restriction with Arc; standard TcpListener values also required set\_nonblocking(true) before TcpListener::from\_std. Other changes included renamed APIs and revised Hyper WebSocket upgrades, and the author says the major upgrade was not hard.

## Context

Fly.io wanted to keep its Rust software up to date and gain access to related crate upgrades after Tokio 0.3 and 1.0 were announced. Its load balancer depends on Tokio, Hyper, and several related crates, so the team waited until much of that ecosystem was ready.

## Approach / What changed

The upgrade notes identify Tokio 0.2-to-1.0 API differences and show workarounds for changed Stream support, relaxed mutability requirements, new AsyncRead and AsyncWrite traits, additional pinning, the missing runtime::Handle::block\_on method, listener nonblocking requirements, and Hyper WebSocket upgrades.

## Takeaways

- Tokio 1.0 foregoes Stream implementations until standard-library stabilization; tokio-stream supplies implementations for TcpListener, Interval, and more.
- AsyncRead::poll\_read and AsyncWrite::poll\_write now return Result<()> rather than byte counts, with ReadBuf::filled() used to calculate bytes read when needed.
- A standard listener passed to tokio::net::TcpListener::from\_std must be set nonblocking first; otherwise accepting connections can hang.

**Tags:** [Hyper](https://yomu.fyi/topic/hyper), [Rust](https://yomu.fyi/topic/rust), [Tokio](https://yomu.fyi/topic/tokio)

- Source: [Fly.io](https://fly.io/blog/the-tokio-1-x-upgrade)
- Source URL: https://fly.io/blog/the-tokio-1-x-upgrade
- Ingested by Yomu: 2026-09-02T11:58:40.034Z

[Read original post](https://fly.io/blog/the-tokio-1-x-upgrade)
