Una expresión cron parece pequeña porque solo describe cuándo despertar un proceso. El coste de producción está alrededor del disparador: entregas duplicadas, ejecuciones solapadas, ventanas perdidas, zonas horarias, reintentos, escrituras parciales y la pregunta que aparece durante un incidente: ¿cómo sabemos que el trabajo terminó correctamente?
Publicado el 7 de octubre de 202613 min de lecturaProgramación, recuperación y responsabilidad
Programar es solicitar un intento de ejecución
El trabajo fiable necesita controles además del reloj
DisparadorAgenda y zona horaria.
AdquirirLease o clave lógica.
EjecutarLotes limitados y checkpoint.
RegistrarResultado y progreso.
RecuperarReintento, replay o escalado.
Los programadores difieren en entrega, retrasos y reintentos. Algunos pueden invocar dos veces; otros retrasan o pierden una ejecución bajo ciertas condiciones; el destino puede rechazar la llamada mucho después de la hora prevista. Trata la invocación como al menos una vez, salvo garantía contractual distinta, y haz idempotente el trabajo. Una clave de nombre de tarea y periodo lógico evita duplicar efectos de negocio.
Fallos que conviene diseñar
Fallo
Síntoma
Respuesta de diseño
Invocación duplicada
Dos facturas, exportaciones o avisos del mismo periodo
Clave idempotente, restricción única y upsert seguro
Solapamiento
Una ejecución nueva compite por estado con la anterior
Lease con vencimiento, concurrencia limitada o partición
Ejecución retrasada o perdida
Informe obsoleto o ventana de sincronización omitida
Watermark y consulta retroactiva del intervalo pendiente
Finalización parcial
Se modifican algunos registros y el job falla
Checkpoint por lotes y replay seguro
Zona horaria o cambio estacional
La tarea local se ejecuta a una hora inesperada
Instantes UTC y zona de negocio explícita
Fallo silencioso
Se invoca el scheduler pero la salida es incorrecta o vacía
Validar postcondiciones y alertar por falta de resultado
Separa el reloj de la intención de negocio
“Cada día a las 02:00” no basta si el negocio usa una zona local o cambia el horario estacional. Decide si el job sigue tiempo transcurrido UTC o calendario local. Persiste el periodo objetivo, no solo la hora de inicio. Una conciliación diaria debe saber qué fecha de negocio cubre aunque empiece tarde.
Limita y observa cada ejecución
Define duración máxima y tamaño de lote. Registra hora programada, inicio real, periodo lógico, intento, checkpoint, filas procesadas, resultado y tipo de error. Guarda el registro antes de efectos irreversibles. Alerta por finalización atrasada, no solo por excepciones: un job puede acabar con éxito y procesar cero registros por una ventana de consulta incorrecta.
Limita los reintentos y aplica backoff exponencial con jitter cuando corresponda, además de un destino terminal como DLQ o revisión operativa. No repitas a ciegas efectos no idempotentes. Define quién puede reprocesar un periodo y cómo se audita.
Cuándo cron debe convertirse en workflow
Una limpieza sencilla quizá solo necesite scheduler y handler idempotente. El trabajo con varias etapas, esperas, aprobación humana, compensaciones o progreso durable necesita un workflow o una máquina de estados respaldada por cola. Mantén el scheduler pequeño: calcula el periodo y encola; el worker lo reclama y procesa con concurrencia limitada.
La sintaxis cron es lo más barato. Los jobs fiables necesitan identidad lógica, efectos idempotentes, control de solapamiento, recuperación de ventanas, reintentos acotados y evidencia de finalización. Diseña esas garantías y luego elige el scheduler.