TL;DR:
hyperis a low-level, high-performance HTTP/1.1 and HTTP/2 library for Rust. It handles the raw protocol; connection management, request/response parsing, keep-alive, and streaming. Most Rust developers don't usehyperdirectly; they useAxum(server) orReqwest(client), which are built on top ofhyper. Usehyperdirectly when you need fine-grained control over the HTTP stack, are building a framework, or have performance requirements that higher-level APIs can't meet.
What Is hyper?
hyper is a correct, fast, and production-battle-tested HTTP implementation in Rust. It is the HTTP engine that powers most of Rust's web ecosystem.
The dependency tree looks like this:
axum ─┐
warp ─┤─→ hyper → tokio → OS networking
reqwest ─┘hyper handles:
- HTTP/1.1 and HTTP/2 protocol parsing
- Connection pooling (client-side)
- Keep-alive, pipelining, flow control
- Streaming request and response bodies
- TLS integration via
rustlsornative-tls
How Do You Use hyper as a Server?
As of hyper 1.x, you implement the Service trait (from Tower) or use hyper's lower-level connection API directly. Most users should use Axum instead.
[dependencies]
hyper = { version = "1", features = ["full"] }
hyper-util = { version = "0.1", features = ["tokio"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "0.1"use hyper::{body::Incoming, Request, Response};
use hyper::server::conn::http1;
use hyper::service::service_fn;
use http_body_util::Full;
use hyper::body::Bytes;
use tokio::net::TcpListener;
async fn handle(_req: Request<Incoming>) -> Result<Response<Full<Bytes>>, hyper::Error> {
Ok(Response::new(Full::new(Bytes::from("Hello from hyper!"))))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:3000").await?;
loop {
let (stream, _) = listener.accept().await?;
tokio::spawn(async move {
http1::Builder::new()
.serve_connection(hyper_util::rt::TokioIo::new(stream), service_fn(handle))
.await
.unwrap();
});
}
}This is significantly more verbose than Axum; which is the point. Use Axum unless you need this level of control.
How Do You Use hyper as an HTTP Client?
reqwest is the recommended HTTP client for most use cases; it wraps hyper with a high-level API. Use hyper directly when you need streaming, connection pooling control, or HTTP/2 push.
use hyper_util::client::legacy::Client;
use hyper_util::rt::TokioExecutor;
use http_body_util::Empty;
use hyper::body::Bytes;
use hyper::Request;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client: Client<_, Empty<Bytes>> =
Client::builder(TokioExecutor::new()).build_http();
let uri = "http://httpbin.org/get".parse()?;
let req = Request::get(uri).body(Empty::new())?;
let res = client.request(req).await?;
println!("Status: {}", res.status());
Ok(())
}How Does hyper Differ From Axum and Reqwest?
hyper is the engine. Axum and Reqwest are the cars; they add routing, extractors, middleware, JSON handling, and ergonomics on top.
| hyper | Axum | Reqwest | |
|---|---|---|---|
| Level | Low-level protocol | High-level server | High-level client |
| Routing | ❌ manual | ✅ built-in | N/A |
| JSON / extractors | ❌ manual | ✅ built-in | ✅ built-in |
| Middleware | Tower Service | Tower layers | ❌ |
| Use case | Framework authors, edge cases | Web APIs, apps | HTTP client code |
| Verbosity | High | Low | Low |
When Should You Use hyper Directly?
Building a custom HTTP framework, writing a reverse proxy, streaming large bodies with precise control, or benchmarking the absolute ceiling of Rust HTTP performance.
- You're building a framework (Axum is built this way)
- You need per-connection hooks not exposed by Axum
- You're implementing an HTTP proxy or load balancer
- You need HTTP/2 server push
- You want to minimize dependencies (no routing overhead)
For everything else; APIs, web apps, microservices; use Axum.
Frequently Asked Questions
Yes; hyper powers Linkerd, Cloudflare services, AWS Lambda's runtime, and many other production systems. It's one of the most battle-tested Rust crates.
hyper 1.0 (released 2023) is a significant API redesign; more modular, removed built-in server utilities (moved to hyper-util), and updated to work with Tower's Service trait. Axum 0.7+ targets hyper 1.x.
hyper itself doesn't; it's TLS-agnostic. Use hyper-rustls (for rustls) or hyper-tls (for native-tls) to add TLS support. Reqwest handles this automatically.
hyper-util is a companion crate providing convenience utilities that were removed from hyper 1.x to keep the core minimal; including TokioIo, client connection pooling, and server utilities.
Sources
- hyper documentation: API reference
- hyper GitHub: Source and examples
- hyper guides: Official guides for server and client usage
Related Glossary Terms
- Axum: High-level web framework built on hyper
- Reqwest: High-level HTTP client built on hyper
- Tower: The
Servicetrait abstraction hyper integrates with - Tokio: The async runtime hyper runs on
- Async/Await: hyper is fully async; all operations return futures
- Rustls: TLS stacks in modern Rust HTTP services are commonly built with rustls
Keep Reading
- Rust vs Go for Backend Development: hyper vs Go's net/http for high-performance HTTP
- Rust at Cloudflare: Cloudflare uses hyper internally for edge HTTP
- Rust on AWS Lambda: hyper as the HTTP layer in serverless Rust

