Rust web backend
Skill fusengine/agents/plugins/rust-expert/skills/rust-web-backend
Redefining development through cognitive automation and collaborative agent systems.
npx -y skills add fusengine/agents --skill rust-web-backendAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 22 stars22 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when building a REST/HTTP backend in Rust — axum routing, extractors, shared state, middleware, error responses, sqlx database access. Not for raw async/concurrency (rust-async-concurrency).
SKILL.md
5.1 KB, ~1.2k tokens by cl100k_base, as published. Nobody here has run it
It also names the honest alternatives — sea-orm for an ActiveRecord-style ORM, diesel for a mature but synchronous alternative needing spawn_blocking — and structured observability via tracing.
Out of scope: raw async/concurrency primitives (channels, locks, task spawning) belong to rust-async-concurrency; cross-domain crate selection belongs to rust-ecosystem-crates. </objective>
Rust Web Backend
Agent Workflow (MANDATORY)
Before building the service, spawn in parallel:
- fuse-ai-pilot:explore-codebase — detect the existing router, state, and DB layer
- fuse-ai-pilot:research-expert — verify current axum/sqlx APIs via Context7/Exa (axum 0.8 changed several APIs)
- mcp__context7__query-docs — pull exact extractor/handler signatures
After building, run fuse-ai-pilot:sniper.
The 2026 standard stack
| Layer | Crate | Why |
|---|---|---|
| Runtime | tokio | De-facto async runtime; everything targets it |
| HTTP framework | axum 0.8.x | Tower-based, extractor ergonomics, minimal magic |
| Middleware | tower / tower-http | Composable layers (trace, cors, timeout, compression) |
| Database | sqlx 0.9 | Async, query! compile-time-checked SQL, no DSL; Postgres/MySQL/SQLite |
| Observability | tracing + tracing-subscriber | Structured, async-aware spans and logs |
Honest alternatives: sea-orm (ActiveRecord-style ORM, higher-level than sqlx), diesel 2.x (mature, synchronous — needs spawn_blocking or a sync pool in async apps). Prefer sqlx for the standard stack; reach for these only when their model fits.
Critical Rules
- axum 0.8 path syntax is
/{id}, not/:id—/*restbecame/{*rest}. The oldmatchitsyntax will not compile. - Errors implement
IntoResponse— never.unwrap()in a handler. Map domain errors to a status + body via one app error type. - Share state with
State<T>, wrapped once — put the pool/config in anArc-friendly struct; extract it withState, do not use globals. sqlx::query!needsDATABASE_URLat compile time — or a committed.sqlx/offline cache (cargo sqlx prepare). Plan this before CI.- No
#[async_trait]on axum extractors — 0.8 uses RPITIT; customFromRequestPartsimpls must drop the macro.
Reference Guide
Concepts
| Topic | Reference | When to Consult |
|---|---|---|
| Architecture | architecture.md | Router, extractors, State, tower middleware layout |
| Error handling | error-handling.md | App error type + IntoResponse |
| Database | database.md | sqlx pool, query!, migrations, alternatives |
| Observability | observability.md | tracing spans, subscriber, request logging |
Templates
| Template | When to Use |
|---|---|
| rest-service.md | Complete minimal REST service (router + state + handlers + errors + tracing) |
Quick Reference
Router with the 0.8 path syntax
let app = Router::new()
.route("/users", get(list).post(create))
.route("/users/{id}", get(show)) // NOT /:id
.with_state(state);
→ See architecture.md
Compile-time-checked query
let user = sqlx::query_as!(User, "SELECT id, name FROM users WHERE id = $1", id)
.fetch_optional(&pool)
.await?;
→ See database.md
Best Practices
DO
- Keep one app error type that implements
IntoResponse. - Layer cross-cutting concerns (trace, timeout, cors) via
tower-http. - Verify queries at compile time with
query!/query_as!.
DON'T
- Use
/:idroute syntax (0.7 and earlier only). .unwrap()in handlers — return a typed error.- Reach for diesel in async code without accounting for its sync nature.
Sources (verified)
- tokio.rs/blog/2025-01-01-announcing-axum-0-8-0 — path syntax, Option extractor,
#[async_trait]removal (fetched 2026-07-05) - crates.io — axum 0.8.9, sqlx 0.9.0, tokio 1.52.3, tracing 0.1.44 (current at fetch)
What ships with it: 5 files
18.8 KB alongside SKILL.md
references/
- architecture.md3.9 KB
- database.md3.6 KB
- error-handling.md3.7 KB
- observability.md3.4 KB
- templates/rest-service.md4.2 KB
Gives 0 of the 12 instructions most data backend skills give in ~1.2k tokens
Counted across 229 of the 229 authors here whose files we hold, read 2026-08-07
- Separate business logic into service layersin 22 of 229, across 15 files
- Retry failures with exponential backoffin 21 of 229, across 14 files
- Select only needed database columnsin 20 of 229, across 13 files
- Abstract data access into repository classesin 19 of 229, across 12 files
- Use centralized error handlersin 17 of 229, across 10 files
- Use AsNoTracking for read-only queriesin 16 of 229, across 4 files
- Use async/await for all I/O operationsin 16 of 229, across 5 files
- Implement structured loggingin 15 of 229, across 4 files
- Use dependency injection for all servicesin 14 of 229, across 2 files
- Use resource-based URLs for REST APIsin 13 of 229, across 7 files
- Invalidate cache after data changesin 13 of 229, across 9 files
- Use a dependency injection containerin 12 of 229, across 4 files
Said here and by no other author read
- explore existing code before building
- research current apis before building
- pull exact handler signatures before building
- run sniper after building
- use axum 0.8 path syntax
- implement IntoResponse for domain errors
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.