ADR-01.002 / 2026-08-15
Registrar eventos con transactional outbox
La recepción de órdenes persiste el estado y el evento OrderReceived de forma atómica mediante un transactional outbox.
Contexto
La recepción de una orden nueva debe conservar de forma durable tanto la orden como la intención de registrar un evento OrderReceived. Una recepción idempotente existente no debe generar un segundo evento, y una carrera por externalReference debe mantener la recuperación de la orden ganadora.
Decisión
La orden nueva y su evento OrderReceived se persisten en la misma transacción. Si falla la escritura en outbox_events, la orden también hace rollback. En una recepción idempotente existente no se crea otro evento. En una carrera por externalReference, el intento perdedor hace rollback antes de recuperar la orden ganadora.
outbox_events registra la intención durable de publicación. Después, OutboxPublisher lee los eventos pendientes (published_at IS NULL), publica a Kafka y marca published_at. Esta secuencia puede redeliverar un evento si Kafka confirma antes de que se actualice la base de datos.
Consecuencias
La transacción de negocio gana atomicidad entre estado y evento. La publicación se realiza mediante un proceso separado y añade procesamiento asíncrono. La ventana entre el ACK de Kafka y la actualización de published_at implica posible redelivery; el flujo es at-least-once y no garantiza exactly-once de extremo a extremo.
Alternativas descartadas
Guardar la orden y publicar directamente a Kafka en pasos independientes puede dejar el estado y el evento descoordinados. Publicar primero y persistir después también permite que una publicación exista sin una orden persistida. Un dual write sin mecanismo de coordinación no ofrece atomicidad entre ambas operaciones.