Por qué elegimos Rust para la próxima generación de nuestro Backend

Estamos construyendo el nuevo backend de nuestros servicios en Rust. No es una moda: es una decisión con ventajas concretas y con costos que conviene decir de frente. Este artículo explica por qué la tomamos, qué usamos y cuándo no la recomendaríamos.
El contexto
Nuestros sistemas manejan datos que no se pueden equivocar: facturas electrónicas del SRI, inventarios, cobros y licencias. En ese tipo de software un error silencioso, como un valor nulo que nadie esperaba o un monto mal redondeado, cuesta más que cualquier ahorro de tiempo de desarrollo. Por eso buscamos un lenguaje que nos obligue a manejar los casos difíciles desde la compilación y no en producción.
Las razones del cambio
Errores que se detectan al compilar
Rust no tiene valores nulos implícitos: lo que puede faltar se declara como Option, y lo que puede fallar devuelve un Result. El compilador te obliga a decidir qué hacer en cada caso. En un sistema de facturación, eso evita toda una familia de fallos por datos faltantes.
Tipos que modelan el negocio
Un comprobante pasa por estados bien definidos. En Rust se expresan como una enumeración, y el compilador avisa si olvidas manejar alguno:
enum EstadoComprobante {
Pendiente,
Recibido,
Autorizado { numero_autorizacion: String },
NoAutorizado { motivo: String },
}
fn debe_reintentar(estado: &EstadoComprobante) -> bool {
match estado {
EstadoComprobante::Pendiente | EstadoComprobante::Recibido => true,
EstadoComprobante::Autorizado { .. } => false,
EstadoComprobante::NoAutorizado { .. } => false,
}
}
Si mañana agregamos un estado nuevo, el código que no lo contemple deja de compilar. Ese es exactamente el tipo de red de seguridad que buscamos.
Memoria segura sin recolector de basura
Rust gestiona la memoria con su sistema de propiedad (ownership y borrowing), sin recolector de basura. Eso elimina categorías enteras de errores de memoria y hace que el consumo de recursos sea predecible. Para servicios que corren todo el día en servidores modestos, es una ventaja práctica.
Concurrencia más segura
El compilador impide, en la mayoría de casos, que dos hilos modifiquen el mismo dato sin coordinación. Para un servicio que atiende muchas peticiones a la vez, esto reduce fallos difíciles de reproducir.
Un solo binario fácil de desplegar
El resultado de compilar es un ejecutable único. No requiere instalar un entorno de ejecución aparte en el servidor, lo que simplifica el despliegue y las actualizaciones.
Lo que usamos
- Axum y Tokio para la API HTTP y la concurrencia asíncrona.
- sqlx para acceder a PostgreSQL de forma asíncrona.
- tower-http para CORS, límites de tamaño y otras capas de protección.
- PostgreSQL como base de datos.
El sitio web público es estático (React) y se comunica con este servicio mediante una API REST.
Los costos reales
- Curva de aprendizaje: Rust exige más tiempo al inicio. Aprender a trabajar con el compilador toma semanas.
- Compilación más lenta: especialmente en compilaciones completas de producción.
- Ecosistema más pequeño que el de Java o JavaScript para algunas necesidades empresariales.
- Menos personas disponibles para mantener el código si el proyecto crece.
No publicamos aquí mediciones de rendimiento porque no hemos hecho una comparación controlada contra otras opciones. Nuestras razones son de corrección y mantenimiento, no de velocidad.
Cuándo no elegirías Rust
Para una aplicación administrativa sencilla, un sitio con formularios o un prototipo que debe salir esta semana, hay opciones más ágiles y perfectamente buenas. Rust tiene sentido cuando el costo de un error es alto, el servicio va a vivir mucho tiempo y quien lo mantiene está dispuesto a aprenderlo.
Conclusión
Elegimos Rust porque queremos que el compilador nos ayude a no equivocarnos en lo que más importa: el dinero y los comprobantes de nuestros clientes. Si estás evaluando qué tecnología usar para tu proyecto, cuéntanos tu caso y te decimos con honestidad cuál conviene.