rust 61 lines · 9 steps

Rate-limiting an expensive Axum route with tower

An Axum PDF-rendering endpoint bounds concurrency and enforces timeouts by layering tower middleware onto a sub-router.

Explained by highlit
1use std::time::Duration;
2 
3use axum::{
4 extract::State,
5 http::StatusCode,
6 response::{IntoResponse, Json},
7 routing::post,
8 Router,
9};
10use serde::{Deserialize, Serialize};
11use tower::limit::ConcurrencyLimitLayer;
12 
13#[derive(Clone)]
14struct AppState {
15 renderer: RenderClient,
16}
17 
18#[derive(Deserialize)]
19struct RenderRequest {
20 template: String,
21 #[serde(default)]
22 payload: serde_json::Value,
23}
24 
25#[derive(Serialize)]
26struct RenderResponse {
27 document_id: String,
28 bytes: usize,
29}
30 
31async fn render_pdf(
32 State(state): State<AppState>,
33 Json(req): Json<RenderRequest>,
34) -> Result<Json<RenderResponse>, StatusCode> {
35 let rendered = state
36 .renderer
37 .render(&req.template, req.payload)
38 .await
39 .map_err(|_| StatusCode::BAD_GATEWAY)?;
40 
41 Ok(Json(RenderResponse {
42 document_id: rendered.id,
43 bytes: rendered.body.len(),
44 }))
45}
46 
47async fn health() -> impl IntoResponse {
48 (StatusCode::OK, "ok")
49}
50 
51pub fn build_router(state: AppState) -> Router {
52 let expensive = Router::new()
53 .route("/render/pdf", post(render_pdf))
54 .layer(ConcurrencyLimitLayer::new(8))
55 .layer(tower_http::timeout::TimeoutLayer::new(Duration::from_secs(30)));
56 
57 Router::new()
58 .route("/health", axum::routing::get(health))
59 .merge(expensive)
60 .with_state(state)
61}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Layers applied to a sub-router protect only its routes, so cheap endpoints like health checks stay unthrottled.
  2. 2tower middleware such as concurrency limits and timeouts composes onto Axum routers without touching handler logic.
  3. 3Axum extractors turn shared state and request bodies into typed handler arguments while the return type maps errors to HTTP responses.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Rate-limiting an expensive Axum route with tower — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code