Saga

Qué es

Saga es un patrón para coordinar una operación de negocio mediante una secuencia de transacciones locales. Cada paso confirma por separado; si el proceso no puede completarse, otras acciones compensan los pasos que ya produjeron efectos.

El patrón sirve para procesos cuya duración, autonomía o recursos hacen inconveniente mantener una transacción global abierta. Su resultado incluye una ejecución completa o una recuperación semántica de la ejecución parcial, bajo condiciones explícitas. No garantiza que nadie haya observado estados intermedios.

El trabajo original de García-Molina y Salem propone dividir transacciones de larga duración y permitir intercalarlas con otras. Las compensaciones corrigen el significado de un resultado parcial sin necesariamente restaurar el estado anterior. El uso actual entre servicios aplica esa idea a participantes con commits locales independientes. Sagas, 1987.

Qué problema resuelve

Confirmar un pedido, reservar inventario, autorizar un pago y organizar el envío pueden depender de sistemas autónomos. Uno puede estar caído cuando los anteriores ya confirmaron. Abrir una transacción que conserve todos sus locks hasta que llegue una respuesta humana o logística suele ser incompatible con el proceso.

Una saga mantiene la obligación de resolver esa ejecución parcial: avanzar cuando sea posible o compensar cuando el negocio deba abandonar la intención. Esta obligación requiere memoria durable, reglas de transición y responsabilidad de recuperación; una lista de llamadas con try/catch no basta.

Cómo funciona

Para una secuencia T1, T2, T3, cada Ti es una transacción local. Si T3 falla antes de confirmar, puede abortar localmente. Los efectos confirmados de T2 y T1 requieren nuevas transacciones, C2 y C1, si la política es compensarlos.

El orden inverso es frecuente cuando existen dependencias, pero el dominio puede requerir otro orden o compensaciones paralelas. Hay que conservar identificadores, parámetros y progreso de cada acción para recuperarla después de un crash. Restaurar un snapshot previo podría sobrescribir trabajo concurrente. Microsoft: Compensating Transaction.

Forward y backward recovery

Forward recovery intenta completar el proceso desde un estado conocido: consultar el resultado incierto, aplicar retry ante un fallo transitorio bajo condiciones seguras o elegir una alternativa de negocio válida. Backward recovery ejecuta compensaciones para abandonar o corregir lo ya realizado.

La política depende del fallo y del punto alcanzado. Después de entregar físicamente un paquete, «cancelar» puede necesitar una devolución, con costos y plazos distintos. Algunos pasos son irreversibles: deben colocarse deliberadamente y acompañarse de una estrategia de finalización o intervención, no de una compensación ficticia.

Ejemplo

Una compra pasa por estos pasos. El ejemplo presupone que todavía se puede cancelar la preparación del envío y que no se capturó el pago:

Paso localEfecto confirmadoCompensación de negocio
Create OrderPedido en preparaciónMarcar pedido cancelado, conservando su historia.
Reserve InventoryUnidades asignadas al pedidoLiberar esa asignación específica.
Authorize PaymentAutorización obtenidaSolicitar anulación de esa autorización.
Arrange ShipmentPreparación logística aceptadaCancelar la preparación si sigue siendo cancelable.

Si la autorización es rechazada definitivamente, se libera inventario y se cancela el pedido. Si la respuesta de logística vence por timeout, primero hay que averiguar si aceptó el trabajo: enviar otro pedido de envío podría duplicarlo.

Devolver dinero tras una captura es otra operación contable, posiblemente con comisiones; no es el rollback del cobro. Una notificación ya recibida tampoco desaparece. Las compensaciones deben producir un estado aceptable ahora, considerando lo que otros actores observaron y cambiaron.

Orchestration y choreography

En orchestration, un coordinador del flujo conserva el progreso y ordena el siguiente paso o la compensación. Facilita localizar la decisión de negocio, pero su estado y recuperación se vuelven parte crítica del sistema.

En choreography, los participantes reaccionan a eventos y las transiciones se distribuyen entre ellos. Reduce la necesidad de un controlador central, pero obliga a hacer visible el flujo, correlacionar eventos y definir quién detecta un proceso incompleto o inicia una compensación. Ningún enfoque elimina la coordinación lógica ni la necesidad de recuperación. Microsoft: Saga distributed transactions pattern.

La elección no determina las garantías de transporte. Ambos pueden recibir duplicados, mensajes tardíos o respuestas perdidas, y necesitan identidades consistentes para interpretar esos intentos.

Failure scenarios

  • Crash tras un commit local: al reiniciar, el flujo debe reconocer el efecto existente y continuar; recordar solo el último comando enviado no prueba el resultado.
  • Timeout con resultado desconocido: consultar o repetir con una identidad protegida por idempotency, sin asumir que no ocurrió nada.
  • Reentrega: at-least-once puede repetir pasos o compensaciones. deduplication puede complementar la idempotencia, siempre vinculada al efecto local correcto.
  • Compensación fallida: conservar la obligación pendiente y reintentar o escalar; no declarar el proceso reparado porque se envió un comando.
  • Mensajes tardíos y carrera con cancelación: una respuesta de éxito no debe reabrir un flujo cancelado. Las transiciones necesitan control de concurrencia y reglas para resolver efectos tardíos.

Los fallos permanentes, errores en la compensación o pérdida de información pueden impedir una recuperación automática. «Eventualmente consistente» necesita supuestos de progreso y un responsable, no una promesa de que el tiempo arreglará el sistema.

Observaciones concurrentes y dual write

Una saga no tiene el aislamiento de una única transacción global. Un lector puede ver el pedido en preparación y el inventario reservado aunque el pago todavía no exista. Otro flujo podría actuar sobre ese estado. Estados explícitos, restricciones locales y operaciones condicionadas deben preservar los invariantes que no pueden esperar a la compensación.

Cada paso que confirma datos y publica un evento independiente conserva el dual-write-problem. La saga no vuelve atómicas esas dos acciones. transactional-outbox puede conservar una intención de publicación junto al commit local; idempotent-consumer aplica idempotencia a los pasos que reciben mensajes. Son mecanismos para fronteras locales, no la coordinación de toda la saga. reliable-messaging conecta esas responsabilidades.

Cuándo usarlo y límites

Usar una saga cuando el negocio admite estados parciales, las compensaciones tienen sentido y el equipo puede operar procesos pendientes durante fallos. Su flexibilidad se paga con lógica de negocio, seguimiento, reintentos, tratamiento de irreversibilidad y reparación.

No elegirla cuando una exposición parcial viola una regla que ninguna acción posterior puede corregir. atomic-commit mediante two-phase-commit puede servir entre recursos compatibles para operaciones acotadas; try-confirm-cancel puede servir si el dominio ofrece reservas. Una transacción local también puede ser suficiente. Saga no reemplaza universalmente ACID: usa transacciones locales y ofrece otro contrato para el proceso completo.