Rust para Web 2026: Axum, Actix, Rocket ou Leptos?

Rust para web em 2026: compare Axum, Actix, Rocket e Leptos e veja qual framework escolher para backend ou full-stack, com API REST de exemplo, Tower middleware e deploy com Docker.

Para desenvolvimento web em Rust, a escolha padrão em 2026 é Axum: framework mantido pela equipe do Tokio, com extractors tipados e middleware do ecossistema Tower. Actix Web entrega a maior performance bruta, Rocket prioriza produtividade e Leptos permite full-stack com frontend Rust compilado para WebAssembly. Neste guia você compara os quatro, constrói uma API REST completa com Axum e vê o caminho de deploy com Docker adotado por empresas como Cloudflare, Discord, Shopify e AWS.

O ecossistema web de Rust amadureceu enormemente nos últimos anos. Em 2026, desenvolver aplicações web com Rust deixou de ser uma aposta experimental para se tornar uma escolha estratégica. A combinação de performance próxima a C, segurança de memória garantida em tempo de compilação e um ecossistema assíncrono robusto torna Rust uma opção cada vez mais atraente para backends de alta carga, APIs REST e até aplicações full-stack.

Se você vem de Node.js, Go ou Python, vai perceber que Rust exige mais rigor no código, mas recompensa com servidores que consomem frações da memória e respondem com latências consistentemente baixas, sem pausas de garbage collector.

Qual framework escolher? Tabela comparativa

FrameworkMelhor paraEstiloFull-stackHighlights
AxumAPIs REST e microserviços (escolha padrão)Handlers async sem macros + TowerNãoExtractors tipados, Tokio nativo, maior comunidade
Actix WebLatência mínima, alta concorrênciaModelo de atoresNãoTopo dos benchmarks TechEmpower
RocketProdutividade, projetos menoresMacros proceduraisNãoConvenção sobre configuração
LeptosFull-stack Rust com SSRComponentes reativosSimFrontend WASM + backend Rust nativo

Principais Frameworks e Bibliotecas

Axum — O Framework Favorito da Comunidade

Axum é mantido pela equipe do Tokio e se tornou o framework web mais popular do ecossistema Rust. Ele se destaca pela ergonomia dos extractors, integração nativa com o Tower middleware ecosystem e tipagem forte para rotas.

Actix Web — Performance Bruta

Actix Web consistentemente lidera os benchmarks do TechEmpower. Usa um modelo de atores e é ideal quando cada milissegundo de latência importa.

Rocket — Simplicidade e Produtividade

Rocket prioriza a experiência do desenvolvedor com macros procedurais que reduzem boilerplate. Ideal para projetos menores ou equipes que valorizam convenção sobre configuração.

Leptos — Full-Stack Rust com SSR

Leptos permite escrever frontend e backend em Rust, com Server-Side Rendering (SSR), hidratação e componentes reativos — tudo compilando para WebAssembly no cliente e Rust nativo no servidor. Compare com Dioxus e Yew no guia de frameworks full-stack.

Configuração Base (Cargo.toml)

[package]
name = "minha-api-web"
version = "0.1.0"
edition = "2021"

[dependencies]
axum = "0.8"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tower = "0.5"
tower-http = { version = "0.6", features = ["cors", "trace", "compression-gzip"] }
tracing = "0.1"
tracing-subscriber = "0.3"
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres"] }

Exemplo Prático: API REST Completa com Axum

Vamos construir uma API de gerenciamento de tarefas com rotas CRUD, middleware de logging e tratamento de erros estruturado.

use axum::{
    extract::{Path, State},
    http::StatusCode,
    routing::{get, post, put, delete},
    Json, Router,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;
use tower_http::trace::TraceLayer;
use tower_http::cors::CorsLayer;

// Modelos
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Tarefa {
    id: u64,
    titulo: String,
    descricao: String,
    concluida: bool,
}

#[derive(Debug, Deserialize)]
struct NovaTarefa {
    titulo: String,
    descricao: String,
}

#[derive(Debug, Deserialize)]
struct AtualizarTarefa {
    titulo: Option<String>,
    descricao: Option<String>,
    concluida: Option<bool>,
}

// Estado compartilhado
type AppState = Arc<RwLock<Vec<Tarefa>>>;

// Handlers
async fn listar_tarefas(State(state): State<AppState>) -> Json<Vec<Tarefa>> {
    let tarefas = state.read().await;
    Json(tarefas.clone())
}

async fn criar_tarefa(
    State(state): State<AppState>,
    Json(nova): Json<NovaTarefa>,
) -> (StatusCode, Json<Tarefa>) {
    let mut tarefas = state.write().await;
    let tarefa = Tarefa {
        id: tarefas.len() as u64 + 1,
        titulo: nova.titulo,
        descricao: nova.descricao,
        concluida: false,
    };
    tarefas.push(tarefa.clone());
    (StatusCode::CREATED, Json(tarefa))
}

async fn obter_tarefa(
    State(state): State<AppState>,
    Path(id): Path<u64>,
) -> Result<Json<Tarefa>, StatusCode> {
    let tarefas = state.read().await;
    tarefas
        .iter()
        .find(|t| t.id == id)
        .cloned()
        .map(Json)
        .ok_or(StatusCode::NOT_FOUND)
}

async fn atualizar_tarefa(
    State(state): State<AppState>,
    Path(id): Path<u64>,
    Json(dados): Json<AtualizarTarefa>,
) -> Result<Json<Tarefa>, StatusCode> {
    let mut tarefas = state.write().await;
    let tarefa = tarefas
        .iter_mut()
        .find(|t| t.id == id)
        .ok_or(StatusCode::NOT_FOUND)?;

    if let Some(titulo) = dados.titulo {
        tarefa.titulo = titulo;
    }
    if let Some(descricao) = dados.descricao {
        tarefa.descricao = descricao;
    }
    if let Some(concluida) = dados.concluida {
        tarefa.concluida = concluida;
    }

    Ok(Json(tarefa.clone()))
}

async fn deletar_tarefa(
    State(state): State<AppState>,
    Path(id): Path<u64>,
) -> StatusCode {
    let mut tarefas = state.write().await;
    let len_antes = tarefas.len();
    tarefas.retain(|t| t.id != id);
    if tarefas.len() < len_antes {
        StatusCode::NO_CONTENT
    } else {
        StatusCode::NOT_FOUND
    }
}

#[tokio::main]
async fn main() {
    // Inicializar tracing
    tracing_subscriber::fmt::init();

    let state: AppState = Arc::new(RwLock::new(Vec::new()));

    let app = Router::new()
        .route("/tarefas", get(listar_tarefas).post(criar_tarefa))
        .route(
            "/tarefas/{id}",
            get(obter_tarefa)
                .put(atualizar_tarefa)
                .delete(deletar_tarefa),
        )
        .layer(TraceLayer::new_for_http())
        .layer(CorsLayer::permissive())
        .with_state(state);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
        .await
        .unwrap();

    tracing::info!("Servidor rodando em http://localhost:3000");
    axum::serve(listener, app).await.unwrap();
}

Tower Middleware — O Poder Composicional

Uma das maiores vantagens do ecossistema Axum/Tower é a possibilidade de compor middleware de forma tipada:

use axum::Router;
use tower::ServiceBuilder;
use tower_http::{
    compression::CompressionLayer,
    cors::CorsLayer,
    limit::RequestBodyLimitLayer,
    trace::TraceLayer,
};
use std::time::Duration;

fn configurar_middleware(app: Router) -> Router {
    app.layer(
        ServiceBuilder::new()
            .layer(TraceLayer::new_for_http())
            .layer(CompressionLayer::new())
            .layer(CorsLayer::permissive())
            .layer(RequestBodyLimitLayer::new(1024 * 1024)) // 1MB
    )
}

Leptos: Full-Stack Rust

Para quem deseja escrever frontend e backend em Rust, Leptos oferece uma experiência semelhante ao React/SolidJS:

use leptos::prelude::*;

#[component]
fn ContadorTarefas() -> impl IntoView {
    let (contagem, set_contagem) = signal(0);

    view! {
        <div class="contador">
            <h2>"Tarefas concluídas: " {contagem}</h2>
            <button on:click=move |_| set_contagem.update(|n| *n += 1)>
                "Concluir tarefa"
            </button>
        </div>
    }
}

Deploy em Produção

Dockerfile Multi-Stage

FROM rust:1.85 AS builder
WORKDIR /app
COPY . .
RUN cargo build --release

FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/minha-api-web /usr/local/bin/
EXPOSE 3000
CMD ["minha-api-web"]

O binário final terá entre 5-15MB e consumirá apenas 2-5MB de RAM em idle, uma fração do que um servidor Node.js ou Python equivalente usaria.

Empresas Usando Rust na Web

  • Cloudflare: Proxy reverso, Workers runtime e ferramentas de rede — grande parte da infraestrutura de borda é Rust
  • Discord: Migrou serviços críticos de Go para Rust, reduzindo latência e consumo de memória drasticamente
  • Shopify: Usa Rust para componentes de alta performance no checkout e processamento de pagamentos
  • AWS: Serviços internos e bibliotecas como o SDK da AWS para Rust
  • Figma: Servidor multiplayer de colaboração em tempo real reescrito em Rust
  • 1Password: Backend de sincronização e criptografia

Como Começar

Se você quer desenvolver aplicações web com Rust, recomendamos o seguinte caminho de aprendizado:

  1. Fundamentos: Domine ownership, borrowing e lifetimes com nosso tutorial de primeiros passos
  2. Async Rust: Entenda futures e o runtime Tokio com a receita de async/await básico
  3. Serialização: Aprenda serde com as receitas de JSON e serialização
  4. Primeira API: Siga o tutorial completo de API REST com Axum
  5. Banco de dados: Conecte ao PostgreSQL com nosso tutorial de Rust + PostgreSQL e a referência de SQLx
  6. Deploy: Configure Docker e GitHub Actions para CI/CD

Conclusão

O desenvolvimento web com Rust em 2026 é uma realidade madura e produtiva. Frameworks como Axum oferecem ergonomia comparável ao Express.js ou Flask, enquanto entregam performance que compete com C++. Se seu projeto precisa de alta performance, baixo consumo de recursos ou latência previsível, Rust é uma escolha excelente para o backend — e com Leptos, até para o frontend.


Veja Também