Objetivos de aprendizaje
Después de leer este artículo podrás:
- Distinguir cron jobs, workers y colas, y qué resuelve cada uno
- Elegir la herramienta correcta para una tarea programada, disparada por eventos o pesada
- Construir una cola mínima con un worker que reintenta en Node.js
Tarde o temprano, alguna tarea se vuelve demasiado lenta para terminar antes de que el usuario reciba la respuesta: enviar un correo, redimensionar una imagen, llamar a una API de terceros inestable. Otras tareas ni siquiera tienen una solicitud, como una limpieza nocturna. Tres herramientas cubren este terreno, y es común confundirlas: cron jobs, workers en segundo plano y colas.
No son rivales. Responden a preguntas distintas: cuándo empieza el trabajo, quién lo hace y dónde espera.
¿Qué es cada uno?#
Un cron job inicia una tarea en los momentos que define una programación. Nada lo dispara salvo el reloj. Mira qué es un cron job para conocer la sintaxis.
Un worker en segundo plano es un proceso de larga duración que trabaja fuera del ciclo de la solicitud. Se define por dónde corre, no por cómo recibe el trabajo. Un worker puede consultar una base de datos, escuchar una cola o ejecutar un bucle.
Una cola es un búfer de trabajos. Un productor (tu app web) agrega un trabajo y sigue con lo suyo. Un worker lo toma después. Las colas suelen agregar reintentos, retrasos, prioridades y límites de concurrencia.
¿En qué se diferencian lado a lado?#
| Cron job | Worker en segundo plano | Cola | |
|---|---|---|---|
| Empieza por | El reloj | Lo que tú programes | Se agregó un trabajo |
| Reacciona a eventos | No | Sí, si escucha | Sí |
| Reintenta si falla | No, salvo que lo programes | Solo si lo programas | Normalmente integrado |
| Sobrevive a un reinicio a mitad de tarea | No | No | Los trabajos pendientes sobreviven, porque están guardados |
| Maneja ráfagas | Mal | Limitado a un proceso | Bien: los trabajos esperan su turno |
| Infraestructura extra | Ninguna | Un proceso | Un broker (por ejemplo, Redis) |
Las dos últimas filas son las que más importan. Una cola separa la producción del trabajo de su ejecución, así que una ráfaga de 1.000 trabajos no necesita 1.000 procesos simultáneos.
¿Cuándo deberías usar cron?#
Usa cron cuando el disparador es el tiempo y la tarea es autónoma: limpiezas nocturnas, reportes diarios, renovación de tokens, sincronizar datos cada hora. No necesita broker ni piezas extra.
Cron se queda corto cuando una ejecución falla y hay que reintentarla, cuando una ejecución dura más que el intervalo o cuando cada ejecución tiene que repartirse en muchas partes. Un programador dentro de la app también se dispara una vez por instancia, así que si ejecutas dos copias de tu app, las dos disparan el trabajo.
¿Cuándo deberías usar una cola y un worker?#
Usa una cola cuando algo pasó y debe seguir un trabajo: un usuario se registró (enviar el correo de bienvenida), se subió un archivo (generar miniaturas), se confirmó un pago (emitir el recibo). La solicitud responde rápido, y el worker termina el trabajo.
Elige una cola cuando necesites alguna de estas cosas:
- Reintentos con backoff para dependencias inestables.
- Control de ritmo, por ejemplo no más de 5 llamadas por segundo a una API.
- Escalar el trabajo, iniciando más procesos worker.
- No perder trabajo cuando un deploy o una caída interrumpe el proceso, porque los trabajos pendientes viven en el broker.
Un trabajo puede ejecutarse más de una vez, por ejemplo cuando un worker se cae a mitad de un trabajo (BullMQ describe "al menos una vez" como su peor caso). Por eso, escribe trabajos idempotentes: ejecutar el mismo trabajo dos veces no debe cobrarle dos veces a un cliente.
¿Cómo se ve una cola mínima en Node.js?#
BullMQ es una biblioteca de colas para Node.js construida sobre Redis. Instálala con npm install bullmq. El productor agrega trabajos:
// producer.js (necesita "type": "module" en package.json)
import { Queue } from "bullmq";
const connection = {
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
};
export const emailQueue = new Queue("emails", {
connection,
defaultJobOptions: {
attempts: 3,
backoff: { type: "exponential", delay: 1000 },
},
});
await emailQueue.add("welcome", { to: "ana@example.com" });El worker es un proceso separado que los consume:
// worker.js
import { Worker } from "bullmq";
const connection = {
host: process.env.REDIS_HOST,
port: Number(process.env.REDIS_PORT),
password: process.env.REDIS_PASSWORD,
};
const worker = new Worker(
"emails",
async (job) => {
// si lanzas un error aquí, BullMQ reintenta el trabajo
console.log("enviando correo de bienvenida a", job.data.to);
},
{ connection, concurrency: 5 },
);
worker.on("failed", (job, err) => {
console.error(`el trabajo ${job?.id} falló:`, err.message);
});Con attempts: 3 y un backoff exponencial de 1.000 ms, un trabajo que falla se reintenta tras unos 1 s y 2 s antes de marcarse como fallido. concurrency: 5 permite que un worker procese cinco trabajos a la vez.
Dos detalles de Redis importan en producción, según la documentación de BullMQ: configura maxmemory-policy como noeviction para que Redis nunca descarte claves de la cola en silencio, y mantén maxRetriesPerRequest en null en las conexiones de los workers (el valor por defecto de Worker).
¿Puedes combinarlos?#
Sí, y la mayoría de las apps maduras lo hacen. Cron es un buen disparador, una cola es un buen búfer y un worker es quien ejecuta. Los job schedulers de BullMQ agregan trabajos a una cola según un patrón cron:
await emailQueue.upsertJobScheduler(
"daily-digest",
{ pattern: "0 0 8 * * *", tz: "America/New_York" },
{ name: "digest", data: {} },
);El patrón tiene seis campos, con los segundos primero, como en los ejemplos de la documentación de BullMQ (este significa 08:00:00 todos los días). Ahora la programación vive en Redis, no en la memoria de un solo proceso, y el trabajo recibe reintentos y control de concurrencia como cualquier otro.
¿Cómo elegir?#
- Una tarea corta e inofensiva según el reloj: cron, dentro de tu app o en el sistema.
- Trabajo causado por un evento, o trabajo que puede fallar y debe reintentarse: cola más worker.
- Una tarea programada que es pesada o no puede perderse: disparador cron que alimenta una cola.
- Una tarea que es simplemente un bucle largo, como el consumidor de un stream: un worker por sí solo.
Empieza con la opción más pequeña. Pasar de cron a una cola después es fácil si la lógica del trabajo vive en una función a la que no le importa quién la llama. Para el lado de Redis, mira qué es Redis y cómo hospedar una aplicación Node.js.
Cómo hacerlo en Square Cloud#
Los workers y los programadores necesitan procesos que sigan encendidos. En Square Cloud, los contenedores están siempre encendidos, sin modo de suspensión, así que un worker o un programador dentro de la app sigue ejecutándose. Con el reinicio automático activado (lo predeterminado en el deploy desde el panel), la aplicación vuelve sola cuando el proceso termina con error.
Para una cola, haz el deploy del worker como una aplicación propia junto a tu app web. La RAM del plan es un pool compartido entre tus aplicaciones, con un mínimo de 256 MB por aplicación en segundo plano y 512 MB por aplicación web. El hospedaje de Redis está disponible desde el plan Standard, en el mismo datacenter que tus apps, con conexiones TLS y persistencia. El panel entrega la URL de conexión y el certificado de la base. Pon los datos de conexión en variables de entorno. Como el TLS es obligatorio y usa certificado propio, agrega al objeto connection de los ejemplos de arriba una opción tls con la CA descargada (por ejemplo tls: { ca: fs.readFileSync("ca.crt") }).
Haz el deploy desde el panel, la CLI o GitHub. El archivo de configuración squarecloud.app es opcional: el panel genera uno en el deploy, con el runtime, la memoria y el archivo principal. Mira las opciones para hospedar APIs para empezar.
Hosting de APIs
APIs en contenedores siempre encendidos, sin cold start
Preguntas frecuentes
¿Una cola es lo mismo que un worker?
No. La cola guarda los trabajos pendientes. El worker es el proceso que los toma de ella y los ejecuta. Necesitas los dos para que una cola sea útil.
¿Puedo usar cron en lugar de una cola?
Solo para trabajo que depende del tiempo. Si una tarea empieza porque algo pasó, como un pago o una subida de archivo, una cola reacciona al instante y reintenta los fallos, algo que cron no hace.
¿Las colas necesitan Redis?
No necesariamente: brokers como RabbitMQ y Amazon SQS funcionan sin Redis. En cambio, bibliotecas como BullMQ para Node.js guardan sus trabajos en Redis y por eso necesitan un servidor Redis.
¿Cómo ejecuto un trabajo recurrente con una cola?
BullMQ tiene job schedulers que agregan un trabajo a la cola según un patrón cron o un intervalo fijo. La programación vive en Redis, y cualquier worker puede procesar el trabajo.
Más en APIs
Ver los 15 artículos- Cómo hospedar una APIHospedar una API es ejecutar su servidor HTTP las 24 horas en una dirección pública con HTTPS. Guía paso a paso con Node.js y Python, pruebas y errores comunes.
- Cómo hospedar una aplicación Node.jsPara hospedar una aplicación Node.js, prepara el package.json, lee el puerto y los secretos del entorno, elige una versión LTS y ejecútala con node. Paso a paso.
- Cómo hospedar FastAPI, Flask o DjangoPara hospedar FastAPI, Flask o Django, ejecuta la aplicación con un servidor de producción (Uvicorn o Gunicorn) en 0.0.0.0. Comandos, ajustes de Django y errores.
- Cómo hospedar una app o script de PythonPara hospedar una app o script de Python, fija la versión, aísla las dependencias en un venv, lee los secretos del entorno y maneja SIGTERM. Guía paso a paso.