Mascota Jacar — leyendo contigo Un portátil cuyos ojos siguen el cursor mientras lees.
Desarrollo de Software

Rust para backend: axum y tokio en servicios reales

Rust para backend: axum y tokio en servicios reales

Actualizado: 2026-05-03

Durante años Rust se posicionó como lenguaje para sistemas — sistemas operativos, drivers, motores de base de datos. Esa percepción ya está desfasada. Con tokio[1] como runtime asíncrono y axum[2] como framework HTTP, escribir servicios web en Rust es razonablemente cómodo, y la diferencia de rendimiento frente a Go o Node.js es real.

Puntos clave

  • El stack tokio + axum + serde + sqlx es la combinación dominante para backend en Rust: rendimiento, seguridad de tipos y ergonomía razonables una vez superada la curva inicial.
  • La curva de aprendizaje es real: ownership, lifetimes y async en Rust desconciertan durante los primeros meses.
  • Rust gana claramente en gateways, proxies y procesadores de eventos; para CRUD típico, Go o Node.js son más productivos.
  • Herramientas como anyhow, tracing, mold y cargo nextest reducen significativamente la fricción de desarrollo.
  • La compilación lenta es el mayor inconveniente operativo: un proyecto medio compila en 30-60s en debug.

El stack actual

Cuando se habla de “backend en Rust”, casi siempre se refiere a esta combinación:

  • tokio: el runtime async dominante. Maneja un número alto de tareas concurrentes con un número pequeño de hilos del SO usando un scheduler work-stealing.
  • axum: framework HTTP construido sobre tower[3] y hyper[4]. Mantenido por el equipo de tokio.
  • serde: el estándar de facto para serializar y deserializar JSON, YAML, TOML y otros formatos.
  • sqlx o diesel: para acceso a base de datos. sqlx, con verificación en tiempo de compilación de queries SQL, es la opción que más crece.

Combinado, este stack permite construir un microservicio JSON sobre Postgres en cantidad similar de código a un equivalente Go, con mejor seguridad de tipos y errores más informativos en compilación.

Un endpoint mínimo en axum

rust
use axum::{routing::get, Router, Json};
use serde::Serialize;

#[derive(Serialize)]
struct Health { status: &'static str }

async fn health() -> Json<Health> {
    Json(Health { 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:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

Tres conceptos clave en este ejemplo:

  • #[tokio::main] arranca el runtime async para que el main sea una función async.
  • Los handlers son funciones async normales — axum se encarga del binding entre tipos y respuestas HTTP.
  • Json<T> es un extractor: como tipo de retorno, axum serializa automáticamente a JSON con el header correcto.

Por qué la curva de aprendizaje pesa

No conviene minimizarlo: Rust tiene una curva de aprendizaje real. Para alguien que viene de Go o TypeScript, los primeros meses son difíciles. Los puntos de fricción principales:

  • Ownership y lifetimes. Rust no recolecta basura — el compilador valida que cada referencia sea válida. Conceptos nuevos para la mayoría de desarrolladores.
  • Async en Rust. Los Future son lazy y dependen del runtime. Errores de compilación con tipos Pin<Box<dyn Future...>> desconciertan al principio.
  • Errores explícitos. Sin excepciones: cada función fallible devuelve Result<T, E> y se propaga con ?. Requiere cambio de mentalidad.
  • Compilación lenta. Un proyecto medio compila en 30-60 segundos en debug y varios minutos en release. Ralentiza el ciclo iterativo.

Para superar esto conviene aceptar 2-3 meses de productividad reducida. Equipos sin esa paciencia suelen abandonar antes de ver los beneficios.

Logotipo de Rust, el lenguaje cuya arquitectura de ownership y async runtime (tokio) permite construir servicios backend de alto rendimiento sin GC

Comparativa pragmática

Aspecto Rust + axum Go + net/http Node + Express
Latencia p99 baja Excelente Muy buena Aceptable
Uso de memoria Muy bajo Bajo Medio-alto
Curva de aprendizaje Empinada Suave Fácil
Velocidad de compilación Lenta Rápida N/A (interpretado)
Ecosistema HTTP Maduro y creciendo Muy maduro Amplísimo
Productividad para CRUD Media Alta Muy alta

Rust gana donde el rendimiento por nodo importa de verdad: servicios bajo carga sostenida, consumo de mensajes de Kafka a tasas altas, gateways que multiplexan miles de conexiones. En servicios CRUD típicos donde el cuello de botella es la base de datos, la ganancia es marginal y el coste de aprendizaje no compensa.

Casos donde compensa

Cuatro tipos de servicios donde Rust se adopta con éxito en producción:

  • Gateways y proxies. Manejar 50.000 conexiones simultáneas con uso de memoria predecible.
  • Procesadores de eventos. Kafka consumers con throughput alto donde Go ya empezaba a notar la presión del GC.
  • Servicios CPU-bound. Procesamiento de imágenes, parsing de logs voluminosos, transformaciones complejas.
  • Componentes embebidos en otros lenguajes. Compilar a librería estática consumida desde Python o Node.js vía FFI.

Para el típico “validar JSON, hacer 3 queries a Postgres, devolver respuesta”, Go o Node.js siguen siendo opciones más productivas.

Patrones que ahorran sufrimiento

Cinco consejos para equipos que adoptan Rust en backend:

  • anyhow para errores en aplicación, thiserror para errores de librería. Hace la propagación de errores razonable sin boilerplate.
  • tracing para logs estructurados. Funciona bien con OpenTelemetry y se integra con axum via middleware.
  • tower middleware. Composición uniforme para logging, autenticación y rate limiting reutilizables.
  • Build incremental con mold como linker. Reduce tiempos de iteración significativamente en Linux.
  • cargo nextest. Un test runner mucho más rápido que cargo test por defecto.

Para la capa de caché sobre Postgres en servicios axum, Redis con estrategias cache-aside es la combinación más habitual. El stack de observabilidad con Grafana integra bien con tracing vía OTLP. Los contenedores de servicios Rust son más fáciles de operar con Podman en entornos rootless.

Conclusión

Rust en backend es una opción seria, no una promesa futura. La combinación tokio + axum es estable, performante y razonablemente productiva una vez superada la curva inicial. Pero no es la respuesta correcta para cualquier servicio — es una elección con trade-offs claros que conviene hacer conscientemente, basándose en cargas de trabajo reales y no en hype.

¿Te ha resultado útil?
[Total: 10 · Media: 4.6]
  1. tokio
  2. axum
  3. tower
  4. hyper

Escrito por

CEO - Jacar Systems

Apasionado de la tecnología, la infraestructura cloud y la inteligencia artificial. Escribe sobre DevOps, IA, plataformas y software desde Madrid.