Primeros pasos con Loco, la respuesta de Rust a Rails
Crea una aplicación web en Rust con Loco, el framework inspirado en Rails. Instala la CLI, genera una API CRUD y añade un worker en segundo plano con Loco 1.2.
Loco es un framework web para Rust inspirado en Rails. Reúne el enrutamiento de Axum, los modelos y migraciones de Sea-ORM, los workers en segundo plano y los generadores de código bajo un único comando: cargo loco.
Si alguna vez has pasado un fin de semana conectando Axum, un ORM, un ejecutor de migraciones y una cola de trabajos antes de escribir una sola línea de lógica de negocio, Loco está pensado para ahorrarte ese esfuerzo. En esta guía instalarás Loco, crearás una aplicación de API, generarás el scaffolding de un recurso y añadirás un trabajo en segundo plano. Muchos tutoriales antiguos están orientados a versiones anteriores a la 1.0, por lo que todos los comandos de esta guía usan la CLI 1.x de Loco 1.2.0. Si eres nuevo en el lenguaje, empieza por los fundamentos de Rust.
Puntos clave
- Loco es un framework web para Rust basado en Ruby on Rails. Está construido sobre Axum para el enrutamiento y sobre Sea-ORM 2.0 para los modelos y las migraciones.
- Instala la CLI con
cargo install loco. También necesitascargo install sea-orm-cli, pero solo si tu aplicación usa una base de datos. - En Loco 1.2,
cargo loco generate scaffoldgenera una migración, un modelo, una entidad, los DTO y un controlador CRUD, y después aplica la migración. No hay un paso de migración independiente. - El servidor de desarrollo de una aplicación Loco nueva escucha en el puerto 5150.
- Durante el desarrollo, los trabajos en segundo plano se ejecutan dentro del propio proceso en modo
BackgroundAsync. En producción, lo habitual es trasladarlos a una cola de Redis, Postgres o SQLite procesada porcargo loco start --worker.
¿Qué es Loco en Rust?
Loco es un framework full-stack para Rust con convenciones muy marcadas (opinionated). Toma por ti las decisiones de stack que un proyecto basado únicamente en Axum deja en tus manos. La página principal de Loco indica que usa Axum como capa HTTP y Sea-ORM 2.0 como ORM. También incluye de serie workers, un planificador (scheduler), envío de correo, almacenamiento y caché. Obtienes una única estructura de proyecto, un único sistema de configuración y una única CLI, así que no tienes que elegir cinco crates ni escribir el código que los conecta. El código fuente está en GitHub. Loco publicó su primera versión estable, la 1.0, en julio de 2026.
¿Qué ideas de Rails adopta Loco?
Loco adopta cuatro hábitos de Rails: cada proyecto sigue la misma estructura predecible, los generadores escriben el código repetitivo, los cambios de esquema se gestionan mediante migraciones versionadas y las tareas lentas se delegan a trabajos en segundo plano. Si conoces Django o Laravel, ya has visto estas mismas ideas con otros nombres.
| Concepto | Qué significa | Comando o ubicación en Loco 1.2 |
|---|---|---|
| Convención sobre configuración | Los archivos están donde el framework espera encontrarlos | Estructura generada en src/ y config/ |
| Generadores | La CLI escribe el código repetitivo | cargo loco generate scaffold, model, controller, worker |
| Migraciones | Cambios de esquema versionados | migration/src/, se aplican automáticamente al generar |
| Trabajos en segundo plano | El trabajo se ejecuta fuera del ciclo de la petición | cargo loco generate worker, perform_later |
¿Cómo se instala Loco y se crea una aplicación?
Instalar Loco requiere dos comandos de cargo, y crear una aplicación, uno más. Como señala el README de Loco, la instalación de sea-orm-cli solo es necesaria si tu aplicación usa una base de datos. Este ejemplo usa SQLite, así que la necesitas:
cargo install loco
cargo install sea-orm-cli
A continuación, genera la aplicación. Si pasas los cuatro flags, el asistente omite sus preguntas, de modo que el comando puede automatizarse en scripts y produce siempre el mismo resultado:
loco new --name tour_app --db sqlite --bg async --assets none
cd tour_app
cargo loco start
Según el tutorial oficial para crear tu primera aplicación, --db sqlite elige SQLite como base de datos, --bg async ejecuta los trabajos en segundo plano dentro del propio proceso y --assets none omite el scaffolding de vistas, de modo que la aplicación solo sirve JSON. La última línea de la salida del arranque confirma que el servidor está en marcha:
listening on port 5150
Por defecto, el servidor de desarrollo escucha en el puerto 5150. Los archivos de configuración establecen el puerto mediante una llamada a get_env que lee la variable de entorno PORT, tal como se muestra en la referencia de configuración, así que puedes cambiarlo ahí. Como has elegido una base de datos, la aplicación también incluye rutas de autenticación integradas en /api/auth/*.
Los tutoriales antiguos instalan un crate llamado loco-cli. Loco 1.0 eliminó ese crate, y ahora la CLI se instala como loco.
¿Cómo se genera un recurso con un scaffold?
Un scaffold de Loco produce una API CRUD funcional y respaldada por base de datos con un solo comando:
cargo loco generate scaffold posts title:string! content:text --no-auth
En Loco 1.2, cargo loco generate scaffold genera una migración, un modelo y una entidad de Sea-ORM, DTO tipados para peticiones y respuestas, y un controlador CRUD. Después aplica la migración y regenera las entidades, por lo que nunca tienes que ejecutar un comando de migración por separado.
La sintaxis de los campos procede de la guía Add a model. Un tipo que termina en !, como title:string!, genera una columna obligatoria. Un tipo sin modificador, como content:text, genera una columna que admite valores nulos, y ^ marca un campo como único. Por defecto, las rutas generadas por el scaffold esperan un JWT, de modo que una petición anónima devuelve un 401. El flag --no-auth hace públicas las rutas, lo que simplifica esta demostración.
Las partes del proyecto generado que se usan en esta guía (se trata de una vista parcial):
tour_app/
├── config/development.yaml
├── migration/src/
└── src/
├── app.rs
├── controllers/posts.rs
├── dtos/
├── models/_entities/
└── workers/
Para probar el nuevo endpoint, reinicia el servidor y envía una petición POST:
curl -X POST -H "Content-Type: application/json" \
-d '{"title":"Tour post","content":"hi"}' localhost:5150/api/posts
La respuesta JSON comienza con {"id":1, y a continuación devuelve el post almacenado.
¿Cómo se añade un trabajo en segundo plano en Loco?
Un trabajo en segundo plano de Loco es un módulo de worker con una struct de argumentos tipada. Se encola con perform_later. Genera uno:
cargo loco generate worker notifier
added: "src/workers/notifier.rs"
injected: "src/workers/mod.rs"
injected: "src/app.rs"
Como explica la guía de workers en segundo plano, el generador siempre llama Worker a la struct y la coloca en su propio módulo, junto a una struct WorkerArgs vacía que debes completar. Esto significa que el worker notifier generado es workers::notifier::Worker. En src/workers/notifier.rs, añade un campo a WorkerArgs y sustituye el cuerpo de perform. Deja build y el resto del archivo generado tal como están:
#[derive(Deserialize, Debug, Serialize)]
pub struct WorkerArgs {
pub post_id: i64,
}
// inside the generated `impl BackgroundWorker<WorkerArgs> for Worker`
async fn perform(&self, args: WorkerArgs) -> Result<()> {
println!("new post created: {}", args.post_id);
Ok(())
}
Después abre src/controllers/posts.rs y añade estas líneas al handler create generado por el scaffold, justo después de la línea que inserta el nuevo post (let item = item.insert(&ctx.db).await?;). Desde Loco 1.0, las claves primarias generadas son de tipo i64, así que item.id encaja en post_id sin necesidad de conversión:
crate::workers::notifier::Worker::perform_later(
&ctx,
crate::workers::notifier::WorkerArgs { post_id: item.id },
)
.await?;
Desde Loco 1.0, perform_later() devuelve el ID del trabajo como un Result<String>, tal como se indica en las notas de la versión 1.0 de Loco. Puedes registrarlo en los logs si quieres hacer un seguimiento de los trabajos más adelante.
Tu config/development.yaml establece workers.mode en BackgroundAsync, que ejecuta los trabajos como tareas de Tokio dentro del propio proceso. El modo BackgroundAsync no necesita ningún backend de colas. En producción, cambia workers.mode a BackgroundQueue, configura una cola de Redis, Postgres o SQLite y procesa los trabajos en un proceso independiente con cargo loco start --worker. Las colas de Postgres y SQLite funcionan con la feature worker predeterminada, mientras que una cola de Redis necesita worker_redis; el backend se selecciona en la configuración mediante queue.kind. El código del worker y del controlador no cambia al hacer el cambio.
¿Para quién es adecuado Loco?
Loco acelera mucho la configuración de un backend en Rust, pero no elimina los costes de escribir Rust:
- Tiempos de compilación. Cada cambio pasa por
rustc, así que el ciclo de edición y recarga es más lento que en los frameworks de Ruby, Python o PHP. - Ecosistema. Hay muchas menos integraciones de terceros, plugins y preguntas resueltas que las acumuladas por Rails o Django.
- Curva de aprendizaje. El código generado sigue dando por hecho que te desenvuelves con soltura con el ownership, async y los traits, y que sabes interpretar los errores del compilador en los handlers.
Loco es una buena opción para desarrolladores que ya conocen Rust y quieren la rapidez de configuración de Rails, así como para desarrolladores de Rails, Django o Laravel que se pasan a Rust de forma deliberada. No es buena elección como primer backend si estás aprendiendo servidores web y Rust al mismo tiempo. Si todavía estás decidiendo si merece la pena aprender Rust para el desarrollo web, lee si los desarrolladores web necesitan Rust.
Conclusión
Loco ofrece a los desarrolladores de Rust lo que Rails ofrece a los de Ruby: una única CLI, una estructura predecible y migraciones y trabajos integrados, todo ello sobre Axum y Sea-ORM. Usa los comandos 1.x de esta guía en lugar de los anteriores a la 1.0 que aparecen en tutoriales antiguos. Como siguiente paso, añade un segundo recurso con cargo loco generate model y, después, sigue la guía de workers en segundo plano para migrar tu cola de BackgroundAsync a un backend persistente.
Preguntas frecuentes
¿Puedo usar middleware y extractores de Axum existentes en una aplicación Loco?
Sí. Loco es, en gran medida, código de integración alrededor de Axum, por lo que los extractores personalizados que implementan FromRequestParts funcionan en los controladores de Loco. Para añadir capas de Tower, como un timeout de tower-http o una capa de sesión, implementa Hooks::after_routes en src/app.rs, que recibe el router de Axum que Loco ya ha construido.
¿Cómo cambio una aplicación Loco de SQLite a Postgres?
Asigna a database.uri en config/development.yaml o config/production.yaml una cadena de conexión postgres://. La configuración generada lee el valor mediante get_env con la variable DATABASE_URL, así que también funciona definir esa variable de entorno. Los valores predeterminados de Loco esperan el usuario loco, la contraseña loco y una base de datos con el nombre de la aplicación y el entorno, como myapp_development. Añadir sslmode=require a la URI activa TLS en Postgres, sin necesidad de ninguna feature adicional de Cargo.
¿Cómo despliego una aplicación Loco en producción?
Compila un binario de release con cargo build --release y cópialo al servidor junto con la carpeta config/. La máquina de destino no necesita la toolchain de Rust ni cargo. Para el empaquetado, cargo loco generate deployment ofrece tres tipos: docker, nginx y lambda. Docker genera un Dockerfile y un .dockerignore, nginx genera una configuración de proxy inverso y lambda genera un punto de entrada para AWS Lambda y añade la dependencia lambda_http. La configuración de producción se encuentra en config/production.yaml.
¿Cuál es la diferencia entre el planificador de Loco y los workers en segundo plano?
Los workers ejecutan los trabajos que tu código encola con perform_later, mientras que el planificador ejecuta trabajos según un calendario. Los trabajos del planificador se declaran en el YAML de configuración, cada uno con una expresión cron o una programación escrita en inglés natural. El valor run indica el nombre de una tarea de Loco registrada, o un comando de shell cuando shell es true. El flag --scheduler ejecuta el planificador junto al servidor sin necesidad de un proceso worker.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k