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.
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.

