A production API with Axum and SQLx
What you end up with: a short-link API that survives contact with production — Postgres with migrations, request validation, structured errors, tracing with request IDs, integration tests against a real database, Docker, and a deploy.

This is the track that matches what Rust backend jobs actually ask for. Most tutorials stop at “here is a handler that returns JSON”. The parts that take real work — connection pooling, error mapping, migrations, testing against a live database, deploying — are exactly the parts covered here.
What you’ll build
Section titled “What you’ll build”POST /linkscreates a short link,GET /:coderedirects and counts the clickGET /linkslists links with cursor pagination- Postgres schema managed by
sqlx-climigrations - Errors as a single
ApiErrortype, mapped to correct status codes withIntoResponse - Input validation that returns useful messages instead of 500s
tracingspans with request IDs, and JSON logs in production- Integration tests that spin up a database per test
- A multi-stage Dockerfile and a deploy to a real host
Before you start
Section titled “Before you start”- Option, Result, and error handling — this track leans on custom error types
- Traits and generics — enough to read extractor bounds
- Concurrency and async — async/await and
Sendbasics - Comfortable with SQL, and with
cargofrom the command line
Articles
Section titled “Articles”- What we’re building: a short link APIthe contract, then the fifteen steps to it
- Setting up Axum and your first routeaxum::serve and a /health that answers
- Routing and extracting path and query parametersextractors, and the order they must be in
- Returning JSON and building a response typeone envelope, one IntoResponse
- Adding SQLx and connecting to Postgresthe pool, and the wrong DATABASE_URL you will write
- Writing your first migrationsqlx migrate, and why the file is plain SQL
- Queries that the compiler checksquery! versus query, and sqlx prepare
- Inserting and reading linksthe two SQL paths the whole service is
- Generating short codes and handling collisionsbase62, a unique index, and a retry
- Validating input and returning proper errorsfrom a bad URL to the right status code
- API key authentication with middlewarea tower layer, and errors from inside it
- Rate limiting per API keya token bucket, and why one instance is not enough
- Structured logging and request tracingone request id through every line
- Integration tests against a real databasesqlx::test and a schema per test
- Docker, config, and deploying to productiona multi-stage build and a single binary
Where the code lives
Section titled “Where the code lives”axum-sqlx-api/ in the examples repository —
one tag per article, plus an answers branch for the exercises.