From a committed outbox row to a handled event

From a committed outbox row to a handled event A sequence diagram generated by Archify. INSERT row (module.entity.verb, payload) COMMIT: the row is durable before publish SELECT … FOR UPDATE SKIP LOCKED Publish once, in order stamp sent (a failed publish leaves the row) deliver (ManualAck, AckExplicit) one delivery per event across workers claim once · open the event's tenant transaction audit Record · notification SendMail · file RemoveBlob ok → ack error: no ack → redelivery; a poison event is dead-lettered jobs.PerTenant: one Tx per tenant module jobs: audit Retention · auth Sweep · billing Renew · file sweep outbox-purge (cron) keeps what has not gone out db.TryLock advisory lock → one process runs a job Publish inside the request transaction Worker role: outbox-relay every second, then events.Consume handles each delivery once jobs.Scheduler: db.TryLock advisory lock → one process runs a job Request Tx · events.Publish · Sequence participant Request Tx events.Publish outbox table · row per event · Sequence participant outbox table row per event outbox-relay · worker, every 1s · Sequence participant outbox-relay worker, every 1s Transport · JetStream or Memory · Sequence participant Transport JetStream or Memory Consumer · group = durable name · Sequence participant Consumer group = durable name events.Consume · claim per delivery · Sequence participant events.Consume claim per delivery Subscription · runs in Tx[Tenant] · Sequence participant Subscription runs in Tx[Tenant] jobs.Scheduler · advisory lock · Sequence participant jobs.Scheduler advisory lock Legend request return async trace default message

Outbox

  • • events.Publish writes the row inside the caller's Tx[Tenant]
  • • events.Relay: SKIP LOCKED, publish once in order, stamp; a failed publish waits

Once per event

  • • Role all: events.Memory() in-process; a fleet: events.JetStream(url), one stream
  • • Durable consumers reconciled at start; events.Consume claims each delivery first

Jobs

  • • db.TryLock: one process per job; Parallel jobs (outbox-relay) take no lock
  • • Module jobs: audit Retention · auth Sweep · billing Renew · file sweep