
Observability for Rust Services With OpenTelemetry
OpenTelemetry gives traces, metrics and logs one vocabulary and one export path. In Rust you keep using tracing and add layers that ship to a collector.
Axum, Actix and Tower in anger: routing, middleware, APIs, and WebAssembly when the code has to run in a browser.

OpenTelemetry gives traces, metrics and logs one vocabulary and one export path. In Rust you keep using tracing and add layers that ship to a collector.

Guessing at performance wastes time. Reproduce the slowness, record a flamegraph and fix the widest bar. This walks one endpoint from 40 ms to 6 ms.

A load test is only useful if it models real traffic and reports percentiles. oha gives a quick check, and k6 scripts realistic user flows with thresholds.

A presigned URL lets the browser upload straight to S3, so your service never touches the bytes. The server signs, the client uploads, and a confirmation step records the result.

A web request should not wait for email or image resizing. Move that work to a queue, run workers that retry on failure, and decide how durable the queue must be.

An idempotency key lets clients retry a POST without charging twice. The server stores the first response and replays it for the same key.

Wire Actix Web 4 to a SQLx 0.9 pool the right way: build the pool once outside the factory closure, share it as web::Data, map errors with ResponseError, and see the 8 versus 28 connection difference when it goes wrong.

Slow clients and oversized requests exhaust connections and memory. Set header and body timeouts, body size limits, concurrency limits and keep-alive bounds at the proxy and in the Axum service with Tower layers.

Treat every upload as hostile: limit the size, sniff the real content type, ignore the client filename, store outside the web root under generated names, scan where needed and serve with safe headers.

The average hides the slow requests users remember. Record latency in histograms, read p50, p95 and p99, learn why tails grow with fan-out, and what typically causes them in Rust services.

Serve the cached value immediately, even if slightly old, and refresh it in the background. Learn the idea, the HTTP Cache-Control directives and an in-process implementation with a freshness window and a grace window.

Connection refused means nothing was listening at that address and port. Check the bind address, localhost versus 127.0.0.1, containers and Docker networks, startup order and the wrong port, with commands for each.
We send one email when a new post is published. No spam.