Agent RulesAgent Rules
Builder
Options
Browse all rules by language and framework
Templates
Pre-built rule sets ready to use
Popular Rules
Top community-ranked rules leaderboard
GuidesAnalyzePricingContact
Builder
OptionsTemplatesPopular Rules
GuidesAnalyzePricingContact

Product

  • Builder
  • Templates
  • Browse Rules
  • My Library

Learn

  • What are AI Agent Rules?
  • Guides
  • FAQ
  • About

Resources

  • Terms
  • Privacy Policy
  • Pricing
  • Contact
  • DMCA Policy

Support

Help keep this project free.

Agent RulesAgent Rules Builder
© 2026 Aurora Algorithm Inc.
Back to Templates

Rust + Axum

Production rules for Rust web applications using Axum. Covers async patterns with Tokio, extractors, Tower middleware, error handling with thiserror/anyhow, SQLx for database access, and proper testing strategies.

rustRust/axumAxum
rust
axum
tokio
async
tower
sqlx
web
Customize in Builder

Details

Language
rustRust
Framework
axumAxum

Rules Content

AGENTS.md
Edit in Builder

Rust Axum Agent Rules

Project Context

You are building a web API with Axum, Tokio, and the Tower ecosystem. Axum leverages Rust's type system to make handlers and extractors composable and misuse-resistant.

Code Style & Structure

- Run `cargo fmt` and `cargo clippy -- -D warnings` before every commit.
- Write `///` doc comments for all public items; include examples for extractors and handler signatures.
- Organize source into modules by domain: `routes/users.rs`, `routes/auth.rs`, not by layer type.
- Use `AppState` as the single shared state type, wrapped in `Arc<AppState>` and passed via `State<Arc<AppState>>`.
- Keep handler functions under 30 lines; delegate business logic to a service layer.

Routing & Application Setup

- Build the router with `Router::new().route("/users", get(list_users).post(create_user))`.
- Use `Router::nest("/api/v1", api_router)` to version the API and group related routes.
- Apply global middleware with `Router::layer(ServiceBuilder::new().layer(...).into_inner())`.
- Apply route-specific middleware with `.route_layer(...)` — it runs only for matched routes, not 404s.
- Use `Router::with_state(Arc::new(AppState::new(...)))` to inject state at the application root.

Extractors

- Use `Path<T>`, `Query<T>`, `Json<T>`, and `State<S>` as function parameters — Axum resolves them automatically.
- Implement `FromRequestParts` for authentication extractors that read headers without consuming the body.
- Implement `FromRequest` for body extractors that consume the request body exactly once.
- Return `Result<T, E>` from `FromRequest` implementations where `E: IntoResponse` to produce typed rejection errors.
- Use `extension::Extension<T>` for request-scoped data injected by middleware (e.g., request ID, user identity).

Middleware

- Compose middleware with `tower::ServiceBuilder` — order from outer to inner: tracing, compression, auth, rate limit.
- Use `tower_http::trace::TraceLayer` to attach structured tracing spans to every request automatically.
- Use `tower_http::cors::CorsLayer` with explicit origin configuration — never `AllowOrigin::any()` in production.
- Write custom Tower middleware by implementing `tower::Layer` and `tower::Service`; use `tower::util::MapResponseLayer` for simple response transformations.
- Propagate request IDs through all middleware layers by injecting them into tracing spans and response headers.

Error Handling

- Define an `AppError` enum with `thiserror::Error`; implement `IntoResponse` to map each variant to a status code and JSON body.
- Use `anyhow::Result` inside services; convert to `AppError` at the handler boundary with `map_err(AppError::from)`.
- Return `(StatusCode, Json<ErrorBody>)` from the `IntoResponse` implementation for a consistent JSON error shape.
- Never expose raw database errors, file paths, or stack traces in the response body.
- Log error details with `tracing::error!` inside the `IntoResponse` implementation before serializing the client-safe message.

Database (SQLx)

- Share a `PgPool` via `Arc<AppState>` — initialize it once at startup with `PgPoolOptions::new()`.
- Use `sqlx::query_as!` for compile-time query checking; supply the return type as the first generic parameter.
- Run migrations at startup with `sqlx::migrate!()` so the schema is always up to date.
- Use `pool.begin().await` for transactions; call `tx.commit().await` on success and let `Drop` handle rollback on early return.
- Map database row types to domain types at the repository layer — never return `sqlx::Row` from a service function.

Type Safety

- Define newtype wrappers for domain identifiers: `struct UserId(Uuid)` with `#[derive(Deserialize, Serialize)]`.
- Use enums to represent finite state: payment status, user role, order lifecycle — make invalid states unrepresentable.
- Validate inputs at the extraction boundary using `validator` crate with `#[validate(...)]` attributes on request structs.
- Use `serde(deny_unknown_fields)` on request structs to reject payloads with unexpected keys.

Testing

- Write integration tests in `tests/` using `axum::test::TestClient` or spawn the app with a `TcpListener` and use `reqwest`.
- Create a `test_app()` helper that builds the `Router` with a test database from `testcontainers`.
- Write unit tests for extractors and service functions inside `#[cfg(test)]` modules.
- Assert on both the HTTP status code and the deserialized JSON response body in every handler test.

Performance

- Profile with `cargo flamegraph` before optimizing; target allocation-heavy paths first.
- Use `Bytes` for zero-copy body handling inside custom extractors and response builders.
- Enable response compression with `tower_http::compression::CompressionLayer` for text-heavy endpoints.
- Configure `PgPoolOptions::max_connections` based on observed load — default of 10 is too low for production.

Related Templates

rust

Rust + WebAssembly

WebAssembly development with Rust, wasm-bindgen, and web integration.