Rust für das Web: Actix Web vs Axum - Vergleich und Interview-Fragen 2026

Ein praxisorientierter Vergleich von Actix Web 4.14 und Axum 0.8 für die Rust-Webentwicklung 2026. Architektur, TechEmpower Round 23 Benchmarks, Entwicklererfahrung und Interview-Fragen für Backend-Rust-Positionen.

Vergleich der Rust-Web-Frameworks Actix Web und Axum für Backend-Entwicklung

Rust-Web-Framework-Adoptionen haben 2026 deutlich zugenommen, und zwei Frameworks dominieren Produktions-Deployments: Actix Web 4.14 und Axum 0.8. Die Wahl zwischen ihnen beeinflusst alles vom Team-Onboarding bis zum Produktionsdurchsatz, und die Frage kommt häufig in Backend-Rust-Interviews vor.

Schnelle Entscheidungshilfe

Actix Web 4.14 führt bei reinem Durchsatz (10-15% mehr Requests pro Sekunde unter hoher Last). Axum 0.8 bietet bessere Ergonomie durch native async-Traits, Tower-Middleware-Komposierbarkeit und engere Tokio-Integration. Für die meisten Teams, die 2026 ein neues Projekt starten, ist Axum die pragmatische Wahl, sofern keine extremen Durchsatzanforderungen bestehen.

Architektur-Unterschiede zwischen Actix Web und Axum

Die architektonische Divergenz zwischen diesen beiden Frameworks erklärt die meisten Performance- und Ergonomie-Trade-offs.

Actix Web startet N Single-Threaded-Tokio-Runtimes, eine pro physischem Kern. Tasks werden an Threads gepinnt ohne Cross-Thread-Datenmigration. Dies eliminiert Work-Stealing-Overhead und Cache-Line-Bouncing, was den konsistenten Durchsatzvorteil unter anhaltender Last erklärt.

Axum läuft auf einer einzelnen Multi-Threaded-Tokio-Runtime mit Work-Stealing. Das Tokio-Team hat Axum speziell entwickelt, um die Fähigkeiten der Runtime zu demonstrieren, daher optimiert jede Designentscheidung für Komposierbarkeit mit dem breiteren Tokio-Ökosystem. Handler sind einfache async-Funktionen, und Middleware verwendet Towers Service-Trait.

actix_hello.rs - Actix Web minimal serverrust
use actix_web::{web, App, HttpServer, HttpResponse};

async fn health() -> HttpResponse {
    HttpResponse::Ok().json(serde_json::json!({ "status": "ok" }))
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/health", web::get().to(health))
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}
axum_hello.rs - Axum minimal serverrust
use axum::{Router, Json, routing::get};
use serde_json::{json, Value};

async fn health() -> Json<Value> {
    Json(json!({ "status": "ok" }))
}

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/health", get(health));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080")
        .await
        .unwrap();
    axum::serve(listener, app).await.unwrap();
}

Beide Beispiele kompilieren und laufen, aber die Unterschiede sind bereits sichtbar. Actix Web verwendet sein eigenes #[actix_web::main]-Makro und gibt std::io::Result zurück. Axum verwendet das Standard-#[tokio::main] und baut Routes über eine Router-Struct. Der Axum-Handler gibt einen typisierten Extractor (Json<Value>) zurück, anstatt manuell eine HttpResponse zu konstruieren.

Performance-Benchmarks: Actix Web 4.14 vs Axum 0.8

Benchmark-Daten aus TechEmpower Round 23 (Januar 2026) liefern den zuverlässigsten Vergleich. Beide Frameworks rangieren in allen Kategorien in der Spitzengruppe.

MetrikActix Web 4.14Axum 0.8.9
Plaintext (req/s)~7.100.000~6.200.000
JSON-Serialisierung (req/s)~1.200.000~1.050.000
DB-Einzelabfrage (req/s)~190.000~175.000
Speicherverbrauch (Hello World)~8 MB~6 MB
P99-Latenz (JSON)1,1 ms1,3 ms

Actix Web hält einen Durchsatzvorteil von 10-15% über alle Kategorien. Axum benötigt etwas weniger Speicher aufgrund der gemeinsamen Tokio-Runtime. Zum Kontext: Beide Frameworks übertreffen Go's Standard-HTTP-Server um das 2-3-fache und Node.js um das 5-8-fache auf vergleichbarer Hardware.

Der Performance-Unterschied ist relevant für Ad-Serving, Echtzeit-Analytics-Pipelines und High-Frequency-Trading-Gateways. Für eine typische REST-API mit 10.000 Requests pro Sekunde sind beide Frameworks weit jenseits des Engpasses, der die Datenbank oder externe Service-Aufrufe sein wird.

Extractors und Request-Handling im Vergleich

Extractors definieren, wie Frameworks eingehende Requests parsen. Axum 0.8 hat hier signifikante Verbesserungen vorgenommen, indem #[async_trait] zugunsten nativer async-Traits entfernt und OptionalFromRequestParts für bessere Option<T>-Handhabung eingeführt wurde.

axum_extractors.rs - Axum 0.8 extractor patternrust
use axum::{
    extract::{Path, Query, State, Json},
    routing::get,
    Router,
};
use serde::Deserialize;
use std::sync::Arc;

#[derive(Deserialize)]
struct Pagination {
    page: Option<u32>,    // defaults to None if missing
    per_page: Option<u32>,
}

// State shared across handlers
struct AppState {
    db_pool: sqlx::PgPool,
}

// Axum 0.8: /{id} syntax (replaced /:id)
async fn get_user(
    State(state): State<Arc<AppState>>,
    Path(user_id): Path<i64>,
    Query(pagination): Query<Pagination>,
) -> Json<serde_json::Value> {
    let page = pagination.page.unwrap_or(1);
    // Query database using state.db_pool
    Json(serde_json::json!({
        "user_id": user_id,
        "page": page
    }))
}
actix_extractors.rs - Actix Web extractor patternrust
use actix_web::{web, HttpResponse};
use serde::Deserialize;

#[derive(Deserialize)]
struct Pagination {
    page: Option<u32>,
    per_page: Option<u32>,
}

struct AppState {
    db_pool: sqlx::PgPool,
}

async fn get_user(
    state: web::Data<AppState>,
    path: web::Path<i64>,
    query: web::Query<Pagination>,
) -> HttpResponse {
    let user_id = path.into_inner();
    let page = query.page.unwrap_or(1);
    HttpResponse::Ok().json(serde_json::json!({
        "user_id": user_id,
        "page": page
    }))
}

Axums Extractors verwenden Tuple-Destructuring direkt in Funktionsparametern. Actix Web wrapped alles in web::Path, web::Query usw. und erfordert .into_inner()-Aufrufe. Beide Ansätze sind zur Compile-Zeit typsicher, aber Axums Ansatz liest sich natürlicher.

Axum 0.8 Breaking Change

Pfadparameter wurden von /:id- zu /{id}-Syntax in Axum 0.8 (via matchit 0.8) geändert. Dies entspricht der OpenAPI-Pfadsyntax. Escaping verwendet doppelte Klammern: {{ für ein literales {.

Middleware-Architektur: Tower vs Actix-Middleware

Middleware-Komposition ist der Bereich, in dem der architektonische Unterschied die größte praktische Auswirkung hat.

Axum verwendet Towers Service- und Layer-Traits. Jede Tower-kompatible Middleware funktioniert mit Axum, einschließlich Rate-Limiter, Tracing, Compression und Authentication-Layers, die für andere Tower-basierte Services erstellt wurden. Diese Komposierbarkeit geht über HTTP hinaus; dieselbe Middleware kann gRPC-Services über Tonic wrappen.

axum_middleware.rs - Tower middleware compositionrust
use axum::{
    Router, middleware,
    routing::get,
    extract::Request,
    response::Response,
};
use tower_http::{
    cors::CorsLayer,
    compression::CompressionLayer,
    trace::TraceLayer,
};
use std::time::Instant;

// Custom middleware as a plain async function
async fn timing_middleware(
    request: Request,
    next: middleware::Next,
) -> Response {
    let start = Instant::now();
    let response = next.run(request).await;
    let duration = start.elapsed();
    tracing::info!("Request took {:?}", duration);
    response
}

fn build_router() -> Router {
    Router::new()
        .route("/api/data", get(|| async { "ok" }))
        .layer(middleware::from_fn(timing_middleware))
        .layer(CompressionLayer::new())
        .layer(CorsLayer::permissive())
        .layer(TraceLayer::new_for_http())
}

Actix Web verwendet sein eigenes Middleware-System mit Transform- und Service-Traits (nicht die von Tower). Middleware aus dem breiteren Tower-Ökosystem erfordert Adapter oder Rewrites.

Für Teams, die bereits in das Tower-Ökosystem über Tonic (gRPC) oder Hyper investiert haben, ist Axums Middleware ein signifikanter Vorteil. Für Teams, die einen eigenständigen HTTP-Service bauen, ist Actix Webs Middleware-System gleichermaßen fähig, nur nicht austauschbar.

Actix Web 4.14 führte Route-Middleware-Validierung ein, die einen Panic auslöst, wenn Handler nach dem Middleware-Wrapping hinzugefügt werden, um Konfigurationsfehler beim Start statt zur Laufzeit zu erkennen.

Bereit für deine Rust-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Datenbankintegration mit SQLx

Beide Frameworks arbeiten gut mit SQLx zusammen, dem async-first SQL-Toolkit, das Queries zur Compile-Zeit validiert. Das Integrationsmuster unterscheidet sich leicht.

shared_db.rs - SQLx with compile-time query validationrust
use sqlx::PgPool;

// This struct works identically with Actix Web and Axum
#[derive(sqlx::FromRow, serde::Serialize)]
struct User {
    id: i64,
    email: String,
    created_at: chrono::NaiveDateTime,
}

// sqlx::query_as! validates against a live DB at compile time
async fn find_user_by_email(
    pool: &PgPool,
    email: &str,
) -> Result<Option<User>, sqlx::Error> {
    sqlx::query_as!(
        User,
        "SELECT id, email, created_at FROM users WHERE email = ",
        email
    )
    .fetch_optional(pool)
    .await
}

Die Datenbankschicht bleibt unabhängig von der Framework-Wahl identisch. SQLx' query_as!-Makro verbindet sich zur Compile-Zeit mit einer Live-Datenbank und validiert Spaltennamen, Typen und Tabellenexistenz. Ein Tippfehler in einem Spaltennamen erzeugt einen Compile-Fehler, keinen Laufzeit-Crash.

Fehlerbehandlungsmuster im Vergleich

Fehlerbehandlung offenbart unterschiedliche Designphilosophien. Actix Web verwendet ResponseError-Trait-Implementierungen. Axum basiert auf IntoResponse kombiniert mit dem Result-Typ.

axum_errors.rs - Axum error handling with IntoResponserust
use axum::{
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};

// Define application-level errors
enum AppError {
    NotFound(String),
    DatabaseError(sqlx::Error),
    ValidationError(String),
}

// Convert errors into HTTP responses
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, message) = match self {
            AppError::NotFound(msg) => (
                StatusCode::NOT_FOUND, msg
            ),
            AppError::DatabaseError(_) => (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Internal server error".to_string(),
            ),
            AppError::ValidationError(msg) => (
                StatusCode::BAD_REQUEST, msg
            ),
        };
        (status, Json(serde_json::json!({ "error": message })))
            .into_response()
    }
}

// Handlers return Result<T, AppError>
async fn get_user(
    axum::extract::Path(id): axum::extract::Path<i64>,
) -> Result<Json<serde_json::Value>, AppError> {
    if id <= 0 {
        return Err(AppError::ValidationError(
            "ID must be positive".to_string()
        ));
    }
    Ok(Json(serde_json::json!({ "id": id })))
}

Axums Ansatz komponiert natürlich mit Rusts ?-Operator und dem Result-Typ. Actix Web erreicht dasselbe durch ResponseError, was die Implementierung sowohl von Display als auch ResponseError-Traits erfordert. Beide funktionieren, aber Axums Pattern fühlt sich idiomatischer für Rust-Entwickler an, die mit dem From-Trait und Error-Propagation vertraut sind.

Wann Actix Web die richtige Wahl ist

Actix Web bleibt in spezifischen Szenarien die richtige Wahl:

  • Maximale Durchsatzanforderungen: Ad-Exchanges, Real-Time-Bidding, Analytics-Ingestion-Pipelines, wo 10-15% mehr req/s den Trade-off rechtfertigen.
  • WebSocket-lastige Anwendungen: Actix Webs WebSocket-Unterstützung ist kampferprobt über mehr Produktions-Deployments. Axums WebSocket-Unterstützung (über axum::extract::ws) funktioniert gut, hat aber eine kürzere Produktions-Historie.
  • Bestehende Actix-Web-Codebases: Migration von Actix Web 3.x auf 4.x ist unkompliziert. Ein Rewrite zu Axum bietet abnehmende Renditen für stabile Services.
  • Team-Vertrautheit: Wenn das Team Actix Web bereits kennt, zahlt sich ein Framework-Wechsel für ergonomische Gewinne selten kurzfristig aus.

Wann Axum die richtige Wahl ist

Axum passt besser in diese Kontexte:

  • Neue Projekte 2026: Die Tokio-Ökosystem-Ausrichtung (Tonic, Hyper, Tower) reduziert Integrations-Reibung.
  • Gemischte gRPC- und HTTP-Services: Tower-Middleware funktioniert über beide Protokolle ohne Adaptierungsschichten.
  • Teams neu in Rust: Axums typgesteuerte Extractors und Compile-Zeit-Fehlermeldungen bieten eine sanftere Lernkurve. Die /{id}-Pfadsyntax (aligned mit OpenAPI) ist sofort vertraut.
  • Microservice-Architekturen: Towers Service-Trait ermöglicht Middleware-Wiederverwendung über Services hinweg und reduziert Boilerplate.

Interview-Fragen: Actix Web und Axum für Backend-Rust-Positionen

Backend-Rust-Interview-Fragen decken zunehmend Web-Framework-Wissen ab. Diese Fragen erscheinen in Senior-Backend- und Systems-Engineering-Interviews.

F: Erklären Sie den architektonischen Unterschied zwischen Actix Webs und Axums Runtime-Modellen.

Actix Web startet eine Single-Threaded-Tokio-Runtime pro CPU-Kern. Tasks werden an Threads gepinnt, was Work-Stealing-Overhead eliminiert. Axum läuft auf einer gemeinsamen Multi-Threaded-Tokio-Runtime mit Work-Stealing. Actix Webs Modell reduziert Cache-Line-Contention unter hoher Last und produziert höheren Durchsatz. Axums Modell vereinfacht Shared-State-Management, da alle Tasks eine Runtime teilen.

F: Wie beeinflusst Axum 0.8s Entfernung von #[async_trait] benutzerdefinierte Extractors?

Axum 0.8 nutzt Rusts native return-position impl Trait in Traits (stabilisiert Ende 2023). Benutzerdefinierte Extractors, die FromRequestParts oder FromRequest implementieren, definieren jetzt async-Methoden direkt ohne das #[async_trait]-Attribut. Dies eliminiert Heap-Allokationen von Box<dyn Future> und verbessert Compile-Zeiten. Bestehende Extractors erfordern das Entfernen des Makros und Anpassungen der Trait-Implementierungen.

F: Beschreiben Sie, wie sich Tower-Middleware von Actix-Web-Middleware unterscheidet.

Tower definiert einen generischen Service<Request>-Trait, der protokoll-agnostisch ist. Ein Tower-Timeout-Layer funktioniert mit HTTP (Axum), gRPC (Tonic) und jedem benutzerdefinierten Protokoll. Actix Webs Middleware verwendet Transform- und Service-Traits, die spezifisch für sein Framework sind. Die praktische Auswirkung: Axum-Middleware ist im Tower-Ökosystem wiederverwendbar; Actix-Web-Middleware ist framework-spezifisch.

F: Wie funktioniert SQLx Compile-Zeit-Query-Validierung, und was sind die Trade-offs?

SQLx' query_as!-Makro verbindet sich während der Kompilierung mit einer Live-PostgreSQL-Datenbank. Es validiert SQL-Syntax, Spaltennamen, Typen und Tabellenexistenz. Der Trade-off: Der Build erfordert Datenbankzugriff, was CI-Pipelines kompliziert. SQLx stellt sqlx prepare bereit, um Offline-Query-Metadaten zu generieren und Validierungsergebnisse in einem .sqlx-Verzeichnis zu cachen, das der Versionskontrolle übergeben wird.

F: Wann wäre die Wahl von Actix Web gegenüber Axum die technisch korrekte Entscheidung?

Actix Web ist korrekt, wenn anhaltender Durchsatz die primäre Einschränkung ist: Ad-Serving, Real-Time-Analytics-Ingestion oder High-Frequency-Trading-Gateways. Das Pinned-Thread-Runtime-Modell eliminiert Work-Stealing-Overhead und produziert 10-15% höhere req/s unter Last. Axum ist korrekt, wenn Komposierbarkeit mit dem Tokio-Ökosystem mehr zählt als marginale Durchsatzgewinne, besonders in Microservice-Architekturen mit HTTP und gRPC.

Häufiger Interview-Fehler

Kandidaten behaupten oft, ein Framework sei universell besser. Starke Antworten erkennen den Trade-off an: Actix Web optimiert für Durchsatz, Axum optimiert für Ökosystem-Komposierbarkeit. Die richtige Wahl hängt von den Systemeinschränkungen ab, nicht von persönlicher Präferenz.

Quellen

Wichtige Erkenntnisse für Rust-Webentwicklung 2026

  • Actix Web 4.14 liefert 10-15% höheren Durchsatz durch sein Pinned-Thread-Runtime-Modell und ist die richtige Wahl für latenz-sensitive, hochdurchsatz-Services
  • Axum 0.8 bietet bessere Ergonomie mit nativen async-Traits, /{id}-Pfadsyntax und voller Tower-Middleware-Kompatibilität über HTTP und gRPC
  • Beide Frameworks verwenden dieselbe Datenbankschicht (SQLx mit Compile-Zeit-Validierung), daher beeinflusst die Wahl nicht die Datenzugriffsmuster
  • Für neue Rust-Webprojekte 2026 ohne extreme Durchsatzanforderungen reduziert Axums Ökosystem-Ausrichtung mit Tokio, Tonic und Tower die langfristigen Wartungskosten
  • Interview-Fragen zu diesem Thema testen das Verständnis von Runtime-Modellen, Middleware-Architektur und Trade-off-Reasoning, nicht Framework-Präferenz
  • Vorbereitung auf Rust-Interviews erfordert das Verständnis der architektonischen Entscheidungen beider Frameworks, nicht nur der API-Syntax

Fang an zu üben!

Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.

Tägliche Challenge

Findest du den Bug in Rust?

Ein echter Codeausschnitt, ein versteckter Bug, ein Versuch pro Tag. Zum Ausprobieren ohne Konto.

Anthony Fillion-Maillet

Geschrieben von

Anthony Fillion-Maillet

Gründer von SharpSkill

Seit über 10 Jahren Fullstack-Entwickler. Er leitet SharpSkill und verantwortet alles, was hier erscheint.

Aktualisiert am 22. August 2026

Tags

#rust
#actix-web
#axum
#web-framework
#backend
#comparison

Teilen

Verwandte Artikel