Payment arrived, the email didn't: consistency with the outbox pattern

Payment, enrollment and notification have to be right together. How we guarantee that in Novademi and PDR with database outboxes and dedicated workers.

Payment arrived, the email didn't: consistency with the outbox pattern

When a payment webhook arrives, three things must happen: the order is marked paid, the student is granted course access and a confirmation email is sent. Call the email service inside the database transaction and a slow provider slows the payment; call it outside and a crash at the wrong moment means the email never goes.

Write first, send later

With the outbox pattern, instead of sending the email we write a "to be sent" record into an outbox table in the same transaction that updates the order. Either both happen or neither does. A separate worker reads the table, sends, and retries with exponential backoff on failure.

  • Novademi has separate commerce and notification outboxes; workers lease rows with FOR UPDATE SKIP LOCKED so no two workers take the same job.
  • Orders carry idempotency keys; if the same request arrives twice, nobody is charged twice.
  • In PDR, email and SMS are fed from the same outbox; the worker runs as its own process in production.

The result: payments are fast and exact, notifications are durable — without extra queue infrastructure, using the database we already trust.

The next system

Tell us how you operate. We’ll build the system.