Skip to content
STACK IT FAST

Axum

Curated OSSClassicRust Web Framework1M+ MAU

Audited from github.com/tokio-rs/axum

Axum is the Tokio project's HTTP routing and request-handling library for Rust: macro-free routing, typed extractors and responses, built on Hyper and using Tower services for all middleware.

Language
Rust
License
MIT
Running for
5 years
Team
1M+ MAU

Why this architecture

Axum skips a custom middleware system and treats every route and layer as a Tower service, so it inherits timeouts, tracing, compression and auth from tower-http and shares middleware with Hyper and tonic code.

Tech stack by layer

7 technologies · audited Oct 2, 2026
Backend & APIs
  • RustOnly implementation language; the workspace forbids unsafe code through workspace.lints.rust (unsafe_code = "forbid").
  • AxumThe axum crate: Router, handlers, extractors and responses, currently versioned 0.8 in its manifest.
  • TowerMiddleware model: every route and layer is a tower::Service, and tower-http supplies timeouts, CORS, tracing and compression.
  • HyperHTTP/1 and HTTP/2 server behind axum::serve, pulled in through the http1/http2 features with hyper-util.
  • TokioAsync runtime used for serving; on wasm32 only the time and rt features are enabled, without networking.
  • WebSocketsOptional ws feature built on tokio-tungstenite for upgrade handling inside ordinary handlers.
Infrastructure & Deploy
  • GitHub ActionsCI.yml runs the test and lint matrix; release-plz.yml automates crate releases and changelogs.
  • cargo-denydeny.toml configures dependency licence and advisory checks for the workspace.

Key architectural decisions

5 decisions
  1. 01

    No middleware system of its own: everything is a Tower service

    The README states that axum does not have its own middleware system and uses tower::Service instead. axum/Cargo.toml depends on tower, tower-layer and tower-service, and enables almost every tower-http feature for docs and tests, so timeouts, tracing, compression and auth come from the shared Tower ecosystem and can be reused with hyper or tonic.

  2. 02

    Split into axum, axum-core, axum-extra and axum-macros crates

    The root Cargo.toml declares a workspace with members "axum" and "axum-*". axum-core holds the stable traits (FromRequest, IntoResponse) with a small dependency set, axum-extra carries optional utilities (cookies, typed headers, protobuf, typed routing), and axum-macros provides proc macros such as debug_handler, so libraries can depend on axum-core without the full framework.

  3. 03

    Macro-free routing on a pinned matchit router

    Routing is ordinary function calls on Router (the README example uses .route("/", get(root))) and axum/Cargo.toml pins matchit = "=0.9.2" for path matching, so route syntax changes only when the maintainers bump that exact version.

  4. 04

    Strict workspace lints shared by every crate

    Cargo.toml sets workspace-wide lints: unsafe_code is forbidden, missing_docs and unreachable_pub warn, and a long clippy list (await_holding_lock, redundant_clone, needless_pass_by_value and more) applies to every member through [lints] workspace = true.

  5. 05

    Examples as a separate workspace of runnable projects

    examples/ has its own Cargo.toml and Cargo.lock with dozens of runnable apps, including sqlx-postgres, diesel-postgres, tokio-postgres, templates-minijinja, jwt, oauth, websockets and testing, so integration patterns are documented as compiling code rather than prose.

How Axum is built

How Axum is structured

Axum is a Cargo workspace, declared in the root Cargo.toml with members = ["axum", "axum-*"]. Four crates live side by side:

Crate Role
axum/ The framework users depend on: Router, handlers, extractors, axum::serve, WebSockets, multipart
axum-core/ Stable core traits and types (FromRequest, IntoResponse) with a deliberately small dependency list
axum-extra/ Opt-in utilities behind features: cookies (signed and private), typed headers, protobuf, JSON lines, typed routing
axum-macros/ Procedural macros such as debug_handler, compiled with syn 2

examples/ is a second workspace with its own Cargo.toml and Cargo.lock, so examples can pull in heavy dependencies (databases, template engines, OAuth clients) without affecting the library's dependency graph.

Backend & APIs

The Rust API is built around three ideas visible in axum/Cargo.toml and the README:

  • Routing without macros. Router::new().route("/", get(root)) is plain Rust. Path matching uses matchit, pinned to an exact version (=0.9.2) so route syntax cannot change on a minor dependency update.
  • Extractors. Handler arguments such as Json<T>, Query<T> and State<T> declare how a request is parsed. The json, query and form features bring in serde_json, serde_html_form and serde_path_to_error, which reports the exact field that failed to deserialize.
  • Tower everywhere. Axum has no middleware API of its own. Routes, handlers and layers are tower::Services, so anything from tower-http (timeouts, CORS, compression, request IDs, tracing, sensitive-header redaction) applies directly. The same middleware can be shared with code written for Hyper or tonic.

Serving goes through Tokio with hyper and hyper-util (features http1 and http2). The optional ws feature adds WebSocket upgrades on top of tokio-tungstenite. A wasm32 target section enables Tokio without networking, and examples/simple-router-wasm shows the router running in WebAssembly.

Data & persistence

Axum has no data layer. Persistence is shown only through examples: examples/sqlx-postgres, examples/diesel-postgres, examples/diesel-async-postgres, examples/tokio-postgres, examples/mongodb, examples/tokio-redis and an in-memory examples/key-value-store. Shared state reaches handlers through the State extractor (examples/dependency-injection).

Build, test & deploy

  • .github/workflows/CI.yml runs the workspace checks and tests; release-plz.yml with release-plz.toml automates version bumps, changelogs and crates.io releases.
  • deny.toml configures cargo-deny and .clippy.toml tunes clippy, on top of the workspace lint table that forbids unsafe_code and warns on dozens of clippy lints.
  • The minimum supported Rust version is set once as rust-version = "1.80" in [workspace.package].
  • axum-macros/tests and trybuild check that macro misuse produces readable compile errors.
  • axum/benches holds benchmarks run with harness = false.

What to copy (and what not to)

Copy:

  • A core crate with a tiny dependency set (axum-core), so ecosystem libraries can implement extractors without pinning the whole framework.
  • Workspace-level lints that every member inherits with [lints] workspace = true. That includes forbidding unsafe where the code does not need it.
  • Examples as compiling projects in a separate workspace, so documentation cannot drift from the API.
  • Reusing an existing middleware abstraction (Tower) instead of inventing one.

Don't copy blindly:

  • The breadth of axum-extra features suits a widely used library. An application should enable only what it uses.
  • Main is a development branch. The README says it carries breaking changes towards 0.9 while released 0.8.x versions live on the v0.8.x branch, so applications should depend on crates.io releases, not on main.

For application structure on top of Axum, see the Rust + Axum + PostgreSQL rules and the server-rendered Axum + htmx + Askama rules.

Sources & repo audit

Audited
Oct 2, 2026
Commit
f8b02f2
License
MIT

Independent analysis of repository at github.com/tokio-rs/axum. Spotted an inaccuracy? Use the claim form to request a correction.

Maintainer? Add the architecture badge to your README
architecture: stackitfast
[![Architecture on STACK IT FAST](https://stackitfast.com/badge/axum.svg)](https://stackitfast.com/project/axum)
Use this stack

Scaffold it with your agent

Paste this prompt into Claude Code, Cursor, Windsurf or AGY to start a project with Axum's architecture.

  1. 1Copy the promptThe full markdown spec, with every layer and decision.
  2. 2Open your AI toolClaude Code, Cursor, Windsurf or Copilot, in a new repo.
  3. 3Paste and scaffoldUse it as the first instruction; review before you ship.
use-this-stack.md · 57 lines · 6.7 KB
# MISSION: Scaffold "Axum" Production Architecture
You are an expert Senior Staff Software Architect and Full-Stack Engineer. Your mission is to scaffold and implement a production-grade, highly reliable, and modular codebase following the proven architecture of **Axum**.
---
## 1. PROJECT SPECIFICATIONS & BENCHMARK
- **Reference Architecture**: Axum
- **What It Does**: Axum is the Tokio project's HTTP routing and request-handling library for Rust: macro-free routing, typed extractors and responses, built on Hyper and using Tower services for all middleware.
- **Domain & Category**: Rust Web Framework
- **Production Scale**: 1M+ MAU
- **Development Mode**: CLASSIC
- **Architectural Rationale**: Axum skips a custom middleware system and treats every route and layer as a Tower service, so it inherits timeouts, tracing, compression and auth from tower-http and shares middleware with Hyper and tonic code.
- **Live Website Reference**: https://docs.rs/axum
- **Source Repository**: https://github.com/tokio-rs/axum
---
## 2. PRODUCTION TECH STACK
- **Full Stack Array**: Rust, Axum, Tokio, Hyper, Tower, WebSockets, GitHub Actions
- **Primary Language(s)**: Rust
- **License of the reference repo**: MIT
- **Backend & APIs**: Rust — Only implementation language; the workspace forbids unsafe code through workspace.lints.rust (unsafe_code = "forbid").; Axum — The axum crate: Router, handlers, extractors and responses, currently versioned 0.8 in its manifest.; Tower — Middleware model: every route and layer is a tower::Service, and tower-http supplies timeouts, CORS, tracing and compression.; Hyper — HTTP/1 and HTTP/2 server behind axum::serve, pulled in through the http1/http2 features with hyper-util.; Tokio — Async runtime used for serving; on wasm32 only the time and rt features are enabled, without networking.; WebSockets — Optional ws feature built on tokio-tungstenite for upgrade handling inside ordinary handlers.
- **Infrastructure & deploy**: GitHub Actions — CI.yml runs the test and lint matrix; release-plz.yml automates crate releases and changelogs.; cargo-deny — deny.toml configures dependency licence and advisory checks for the workspace.
---
## 3. KEY ARCHITECTURAL DECISIONS (audited from https://github.com/tokio-rs/axum @ f8b02f2)
1. **No middleware system of its own: everything is a Tower service**: The README states that axum does not have its own middleware system and uses tower::Service instead. axum/Cargo.toml depends on tower, tower-layer and tower-service, and enables almost every tower-http feature for docs and tests, so timeouts, tracing, compression and auth come from the shared Tower ecosystem and can be reused with hyper or tonic.
2. **Split into axum, axum-core, axum-extra and axum-macros crates**: The root Cargo.toml declares a workspace with members "axum" and "axum-*". axum-core holds the stable traits (FromRequest, IntoResponse) with a small dependency set, axum-extra carries optional utilities (cookies, typed headers, protobuf, typed routing), and axum-macros provides proc macros such as debug_handler, so libraries can depend on axum-core without the full framework.
3. **Macro-free routing on a pinned matchit router**: Routing is ordinary function calls on Router (the README example uses .route("/", get(root))) and axum/Cargo.toml pins matchit = "=0.9.2" for path matching, so route syntax changes only when the maintainers bump that exact version.
4. **Strict workspace lints shared by every crate**: Cargo.toml sets workspace-wide lints: unsafe_code is forbidden, missing_docs and unreachable_pub warn, and a long clippy list (await_holding_lock, redundant_clone, needless_pass_by_value and more) applies to every member through [lints] workspace = true.
5. **Examples as a separate workspace of runnable projects**: examples/ has its own Cargo.toml and Cargo.lock with dozens of runnable apps, including sqlx-postgres, diesel-postgres, tokio-postgres, templates-minijinja, jwt, oauth, websockets and testing, so integration patterns are documented as compiling code rather than prose.
---
## 4. NON-NEGOTIABLE ARCHITECTURAL GUARDRAILS
1. **Monorepo & Modular Separation**:
   - Structure as a Turborepo monorepo with strict package boundaries:
     - `apps/web`: Application UI, routing, layouts, and server endpoints.
     - `packages/ui`: Shared design tokens, CSS variables, and Radix UI primitive components.
     - `packages/db`: Database schemas, client singleton, declarative migrations, and seed scripts.
     - `packages/config`: Shared TypeScript, ESLint, and build configurations.
2. **Strict Type Safety & Zero `any` Policy**:
   - Enable `strict: true`, `noImplicitAny: true`, and `strictNullChecks: true`.
   - Validate ALL external inputs, API request bodies, and query parameters with **Zod** schemas before execution.
3. **Frontend & Rendering Guidelines**:
   - Isolate interactive UI state to leaf components. Keep core pages lightweight and performant.
4. **Design System & Aesthetics**:
   - Keep every color, radius, shadow and font in a single token file (CSS variables) and consume tokens everywhere; never hardcode hex values in components.
   - Prefer crisp 1px borders and one subtle shadow scale over blurry default shadows. Pair one sans-serif for body/headings with one monospace for tags, badges, metrics, and code.
5. **Data Layer & Reliability**:
   - Write declarative schema definitions with foreign keys, composite indexes on queried filters, and automated timestamp triggers.
   - Use connection pooling and prepared statements for serverless database execution.
---
## 5. STEP-BY-STEP SCAFFOLDING ROADMAP
- **Phase 1: Workspace & Root Config**: Initialize package manager, monorepo configuration (`turbo.json`, `tsconfig.base.json`, `package.json`).
- **Phase 2: Database Schema & Client**: Set up the data layer: client, connection pool, models, and migration scripts.
- **Phase 3: Design Tokens & UI Primitives**: Build accessible `Button`, `Input`, `Card`, `Badge`, and layout wrappers inside `packages/ui`.
- **Phase 4: Core Application Routes & Handlers**: Implement primary authentication, user session handling, and application routes.
- **Phase 5: Quality Assurance & Build Verification**: Run `tsc --noEmit`, ESLint, Prettier, and smoke test suites to ensure zero compilation or runtime errors.
---
## 6. EXECUTION INSTRUCTIONS
1. Review all specifications, architectural guardrails, and stack choices above.
2. Present the full monorepo directory tree structure.
3. Systematically generate the complete, production-ready codebase according to the 5-phase roadmap above — starting with the root workspace setup, followed by the database schema, UI design system package, and full-stack application routes until the repository is fully scaffolded and ready to run.
Scaffolded something with this prompt?
Would you pick this stack for a rust web framework project?

Frequently asked about Axum

What is Axum built on?

Axum is built on Tokio for async I/O, Hyper for the HTTP/1 and HTTP/2 server, and Tower for middleware. It has no middleware system of its own; every layer is a tower::Service, and tower-http provides timeouts, CORS, compression and tracing.

Is Axum a full web framework like Rails?

No. Axum covers routing, request extraction and responses. Templates, database access, sessions and auth come from other crates; the repository examples show sqlx, Diesel, tokio-postgres, MiniJinja, JWT and OAuth integrations as separate runnable projects.

Does Axum use macros for routing?

No. Routes are declared with plain method calls such as Router::new().route("/users", post(create_user)). The optional axum-macros crate only adds helpers like debug_handler for clearer compiler errors.

Which Axum version is current?

The axum crate manifest on the audited main branch is at 0.8, and the README notes that main is moving towards 0.9 with breaking changes while released 0.8.x versions live on the v0.8.x branch.

One email a month: new deep dives and stack trends

New source-audited architectures, head-to-head comparisons and the monthly stack report. No spam, unsubscribe anytime.

use-this-stack.md