## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

# ADR-002: Axum como Backend Framework

Status: Accepted | Implemented Date: 2024-11-01 Deciders: Backend Architecture Team Technical Story: Selecting REST API framework with optimal async/middleware composition for Tokio ecosystem

## Decision

Usar Axum 0.8.6 como framework REST API (no Actix-Web, no Rocket) para exponer 40+ endpoints de VAPORA.

## Rationale

1. Composable Middleware: Tower ecosystem provides first-class composable middleware patterns
2. Type-Safe Routing: Router defined as strong types (not string-based paths)
3. Tokio Ecosystem: Built directly on Tokio (not abstraction layer), enabling precise async control
4. Extractors: Powerful extractor system (`Json`, `State`, `Path`, custom extractors) reduces boilerplate
5. Performance: Zero-copy response bodies, streaming support, minimal overhead

## Alternatives Considered

### ❌ Actix-Web

- Mature framework with larger ecosystem
- Cons: Actor model adds complexity, different async patterns than Tokio, harder to integrate with Tokio primitives

### ❌ Rocket

- Developer-friendly API
- Cons: Synchronous-first (async as afterthought), less composable, worse error handling

### ✅ Axum (CHOSEN)

- Minimal abstraction over Tokio/Tower
- Pros: Composable, type-safe, Tokio-native, growing ecosystem

## Trade-offs

Pros:

- ✅ Composable middleware (Tower trait-based)
- ✅ Type-safe routing with strong types
- ✅ Zero-cost abstractions, excellent performance
- ✅ Perfect integration with Tokio async ecosystem
- ✅ Streaming responses, WebSocket support built-in

Cons:

- ⚠️ Smaller ecosystem than Actix-Web
- ⚠️ Steeper learning curve (requires understanding Tower traits)
- ⚠️ Fewer third-party integrations available

## Implementation

Router Definition:

    #![allow(unused)]
    fn main() {
    let app = Router::new()
        .route("/api/v1/projects", post(create_project).get(list_projects))
        .route("/api/v1/projects/:id", get(get_project).put(update_project))
        .route("/metrics", get(metrics_handler))
        .layer(TraceLayer::new_for_http())
        .layer(CorsLayer::permissive())
        .layer(Extension(Arc::new(app_state)));

    let listener = TcpListener::bind("0.0.0.0:8001").await?;
    axum::serve(listener, app).await?;
    }

Key Files:

- `/crates/vapora-backend/src/main.rs:126-259` (router setup)
- `/crates/vapora-backend/src/api/` (handlers)
- `/crates/vapora-backend/Cargo.toml` (dependencies)

## Verification

    # Build backend
    cargo build -p vapora-backend

    # Test API endpoints
    cargo test -p vapora-backend -- --nocapture

    # Run server and check health
    cargo run -p vapora-backend &
    curl http://localhost:8001/health
    curl http://localhost:8001/metrics

Expected: 40+ endpoints accessible, health check responds 200 OK, metrics endpoint returns Prometheus format

## Consequences

- All HTTP handling must use Axum extractors (learning curve for team)
- Request/response types must be serializable (integration with serde)
- Middleware stacking order matters (defensive against bugs)
- Easy to add WebSocket support later (Axum has built-in support)

## References

- Axum Documentation
- `/crates/vapora-backend/src/main.rs` (router definition)
- `/crates/vapora-backend/Cargo.toml` (Axum dependency)

Related ADRs: ADR-001 (Workspace), ADR-008 (Tokio)