Tower (Rust): Service Trait & tower-http Guide 2026

Max WellsMax WellsFounder of Rustify

TL;DR: Tower is a Rust library that defines the Service trait: a single abstraction for any component that processes a request and returns a response. It is the foundation of Axum's middleware system. Any Tower-compatible middleware works across Axum, Hyper, Tonic, and other frameworks without modification. Tower does not run code; it defines interfaces that the async ecosystem builds on.


What Is Tower?

Tower is a library of reusable, composable components for building async Rust network services; centered on the Service trait, which abstracts over anything that takes a request and returns a response.

Tower was created to solve a recurring problem in the async Rust ecosystem: every framework invented its own middleware interface, making middleware non-portable. A logging middleware written for one framework could not be reused in another. Tower defines a single, universal interface that frameworks, clients, and middleware all implement.

Axum, Hyper, Tonic (gRPC), and reqwest all build on Tower. This means a rate-limiting middleware written against the Service trait works identically whether it wraps a web server handler or an HTTP client.


What Is the Service Trait?

The Service trait is Tower's core abstraction; a type that asynchronously processes a request and returns a response or an error.

pub trait Service<Request> {
    type Response;
    type Error;
    type Future: Future<Output = Result<Self::Response, Self::Error>>;
 
    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
    fn call(&mut self, req: Request) -> Self::Future;
}
  • poll_ready; checks whether the service is ready to accept a request (used for backpressure)
  • call; processes the request and returns a future that resolves to the response

Every Axum route handler, every middleware layer, and the router itself implements Service. This uniformity is what makes composition possible.


How Does Tower Middleware Work?

Tower middleware is a type that wraps an inner Service, intercepts requests before passing them on, and can inspect or modify the response; implemented via the Layer trait.

use tower::{Service, Layer};
 
// A Layer produces a new Service wrapping an inner one
pub trait Layer<S> {
    type Service;
    fn layer(&self, inner: S) -> Self::Service;
}

Stacking layers with ServiceBuilder:

use tower::ServiceBuilder;
use tower_http::{trace::TraceLayer, compression::CompressionLayer, timeout::TimeoutLayer};
use std::time::Duration;
 
let service = ServiceBuilder::new()
    .layer(TimeoutLayer::new(Duration::from_secs(10)))
    .layer(TraceLayer::new_for_http())
    .layer(CompressionLayer::new())
    .service(my_handler);

Layers are applied bottom-up: the last .layer() call is the outermost wrapper, so TimeoutLayer runs first on every request.

In Axum, .layer() on a Router uses the same mechanism:

let app = Router::new()
    .route("/", get(handler))
    .layer(TraceLayer::new_for_http())
    .layer(CompressionLayer::new());

What Is tower-http?

tower-http is a companion crate that provides HTTP-specific Tower middleware; the most commonly used middleware in Axum applications.

MiddlewareWhat it does
TraceLayerLogs requests and responses with tracing
CorsLayerAdds CORS headers
CompressionLayerGzip/brotli response compression
TimeoutLayerReturns 408 if handler exceeds duration
RequestIdLayerAssigns a unique ID to each request
SetResponseHeaderLayerInjects arbitrary response headers
ValidateRequestHeaderLayerRejects requests missing expected headers

All of these work with any Tower-compatible framework, not just Axum.


How Do You Write a Custom Tower Service?

Implementing Service directly requires boilerplate; for simple cases, Axum's middleware::from_fn is the ergonomic alternative.

Custom Service implementation (for library authors or complex cases):

use std::task::{Context, Poll};
use tower::Service;
 
#[derive(Clone)]
struct LoggingService<S> {
    inner: S,
}
 
impl<S, Req> Service<Req> for LoggingService<S>
where
    S: Service<Req>,
    Req: std::fmt::Debug,
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = S::Future;
 
    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.inner.poll_ready(cx)
    }
 
    fn call(&mut self, req: Req) -> Self::Future {
        println!("Request: {req:?}");
        self.inner.call(req)
    }
}

For application code, axum::middleware::from_fn is simpler:

async fn log_requests(request: Request, next: Next) -> Response {
    println!("{} {}", request.method(), request.uri());
    next.run(request).await
}

Frequently Asked Questions

No. Tower's Service trait abstracts over any request/response pattern. It is used for HTTP servers (Axum, Hyper), gRPC servers and clients (Tonic), HTTP clients (Tower-wrapped reqwest), and even internal service-to-service communication. The abstraction is protocol-agnostic.

Tower defines the Service and Layer traits and provides general-purpose middleware (retry, timeout, rate limiting, load balancing). tower-http builds on top of Tower with HTTP-specific middleware that understands http::Request and http::Response types. For web development, you use both.

Not for basic usage. Axum's .layer() API abstracts away the Service trait for common cases. Tower internals become relevant when writing custom middleware, debugging type errors in middleware stacks, or integrating with non-Axum Tower-compatible services.

poll_ready signals whether a service is ready to accept a new request; it is Tower's backpressure mechanism. A service can return Poll::Pending to pause the caller until capacity is available (useful for rate limiters and connection pools). For simple stateless middleware, poll_ready delegates directly to the inner service.


Sources


  • Middleware: How middleware is used in Axum and Actix Web
  • Axum: Web framework built entirely on Tower
  • Tokio: The async runtime Tower services execute on
  • Hyper: Hyper integrates with Tower's Service abstraction
  • Tonic: Tonic builds gRPC middleware and interceptors on top of Tower
  • Tracing: Tower layers commonly emit structured tracing spans and events

Keep Reading

Ready to Land a $120k+ Rust Job in the US or Europe?