Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

E. Performance

Per request

What lesto costs over the axum::Router it builds on, per request, measured through tower::Service calls with no networking (benches/overhead.rs, cargo bench -p lesto; an Apple laptop, best of five rounds of 200,000 requests):

Requestaxum 0.8lesto
GET /hello616 ns911 ns
POST /items, JSON body validated, status = 2011,187 ns1,498 ns
GET /missing → 404 problem+json388 ns1,260 ns
GET a handler returning HttpError::not_found805 ns1,215 ns

The difference is what lesto adds: the request span, the panic catcher, and an RFC 9457 body where axum answers with none. A 422 costs more again (about 3.0 µs) because it also runs garde and reports every failed check with its location — plain axum does not validate at all, so there is nothing to compare it with.

Trace::off() is not on that list on purpose: it saves about 13 ns, because it is a branch inside a layer that is installed anyway. Use it when you do not want a request span, not when you want speed. scripts/bench-http.sh runs the same application behind oha over a real socket, where the numbers above are lost in the noise of the network.

Build time

Build time is the other cost, and the reason otel is not a default feature. examples/02-notes (sqlite), measured 2026-09-23 on an Apple Silicon laptop with the workspace’s dev profile (dependencies at opt-level = 3):

cratesclean buildrebuild after editing the app
without otel17794 s1.0 s
with otel210118 s1.1 s

The OpenTelemetry SDK, the OTLP exporter and its HTTP client add 33 crates and about a quarter to a clean build; a rebuild of your own code does not notice. Turn it on where telemetry is exported, typically in the deployed build.