---
name: rust-axum-api
description: "High-performance Rust APIs with Axum + Tokio + sqlx: typed routes, extractors, async DB, deploy small. Scaffolds Axum apps with proper extractors, tower middleware, sqlx async DB, and the Dockerfile that ships a 20MB image."
license: MIT
---

# Rust Axum API

Scaffold production-ready HTTP services in Rust using Axum, Tokio, and sqlx. This skill generates a working project with typed handlers, tower middleware wired up, an async Postgres pool, and a multi-stage Dockerfile that produces a tiny statically-linked image. It's aimed at developers who want the performance and type-safety of Rust for backend services without spending a day assembling boilerplate from blog posts.

## When to use it

- Starting a new JSON API or microservice and you want sqlx + Axum set up correctly the first time.
- Adding routes to an existing Axum app and you want consistent extractor/handler signatures.
- You need a small container image for cost-sensitive deploys (Fly.io, Cloud Run, a cheap VPS).
- Replacing a Node/Python service where p99 latency or memory footprint matters.

## What it does

The skill lays down a `Cargo.toml` with `axum`, `tokio` (with the `macros` and `rt-multi-thread` features), `sqlx` (`runtime-tokio-rustls`, `postgres`, `macros`), `tower`, `tower-http`, and `serde`. It generates:

- A `Router` built with `.route("/path", get(handler))` and merged sub-routers.
- Handlers using real extractors — `Path<T>`, `Query<T>`, `Json<T>`, and `State<AppState>` — returning `Result<Json<T>, AppError>` where `AppError` implements `IntoResponse`.
- A shared `PgPool` created via `PgPoolOptions::new().connect(&url)`, stored in `State` and cloned cheaply per request.
- Compile-time-checked queries with the `sqlx::query!` / `query_as!` macros (backed by `sqlx-cli` and a `.sqlx` offline cache).
- `tower-http` layers: `TraceLayer`, `CorsLayer`, and timeout/compression as needed.
- A `migrations/` folder runnable with `sqlx migrate run`, and a distroless/scratch Dockerfile.

## Usage

```bash
curl -fsSL --create-dirs -o ~/.claude/skills/rust-axum-api/SKILL.md https://claudeskil.com/skills/rust-axum-api/SKILL.md

# then, in your project
cargo sqlx prepare          # build the offline query cache
cargo run                   # serves on 0.0.0.0:3000
docker build -t my-api .    # ~20MB final image
```

A generated handler looks like:

```rust
async fn get_user(
    State(pool): State<PgPool>,
    Path(id): Path<i64>,
) -> Result<Json<User>, AppError> {
    let user = sqlx::query_as!(User, "SELECT id, name FROM users WHERE id = $1", id)
        .fetch_one(&pool)
        .await?;
    Ok(Json(user))
}
```

## Tips & gotchas

- `query!` macros hit the database at **compile time**. Set `DATABASE_URL` or commit the `.sqlx` cache (`cargo sqlx prepare`) so CI/Docker builds don't need a live DB.
- Extractor order matters: body-consuming extractors like `Json` must be the **last** argument in a handler.
- For the tiny image, build with the `x86_64-unknown-linux-musl` target so the binary runs on `scratch`/distroless without glibc.
- Add `TraceLayer` last in your layer stack so it wraps everything beneath it.

## FAQ

**Does it use SeaORM or Diesel?** No — it uses sqlx with raw, compile-checked SQL. You write SQL, sqlx verifies it against your schema.

**How is the image only ~20MB?** A musl static build copies a single binary into a `scratch` base; there's no runtime, interpreter, or OS layer.

**Can I add auth/middleware?** Yes — write a `tower` layer or an extractor (e.g. a `FromRequestParts` impl for a `Claims` type) and attach it with `.layer()` or per-route.
