Payments & Money APIs · Webhooks, Orchestration & Recurring Payments
Orchestrating Orders, Inventory & Payments
Outbox, sagas and timeouts across order, stock and payment services.
Checkout touches several systems: reserve inventory, create/confirm payment, create order, send confirmation, fulfil. Without distributed transactions, use a saga: each step has a compensation (release stock, void/refund payment), state is persisted, and timeouts trigger compensations (e.g. reservation expires after 15 minutes if payment isn't confirmed). Publish events with the transactional outbox so "order paid" is never lost or emitted for a rolled-back transaction.
Checkout saga
| Step | Action | Compensation |
|---|---|---|
| 1. Reserve stock | Hold items with TTL | Release reservation |
| 2. Authorize/charge | PaymentIntent confirm | Void (if authorized) / refund (if captured) |
| 3. Confirm order | State → paid, outbox event | Cancel order |
| 4. Fulfil | Pick, pack, ship | Return flow |
| Timeout | No payment in 15 min | Release stock, cancel order |
Python (outbox in the same transaction)
async def mark_paid(order_id: str, event_id: str):
async with db.transaction():
if not await transition(db, order_id, "paid", event_id=event_id):
return
await db.execute(
"INSERT INTO outbox(id, topic, key, payload) VALUES ($1, 'orders.paid', $2, $3)",
uuid7(), order_id, json.dumps({"order_id": order_id, "event_id": event_id}))
# a relay publishes outbox rows to the broker; consumers (fulfilment, email) dedupe by id
Common pitfalls
- Charging before checking stock availability (refund churn).
- Emitting events outside the DB transaction.
- Reservations that never expire.
Key points
- Saga with compensations
- Outbox for reliable events
- Timeouts on reservations and payments
Further reading: microservices.io: Saga
Practice questions
What compensation applies if stock can't be allocated after a payment was authorized?
Answer
Void the authorization (or refund if already captured), cancel the order and notify the customer.
Why use a transactional outbox for 'order paid' events?
Answer
It writes the event in the same DB transaction as the state change, so the event is published if and only if the change committed.
Open in the app to mark lessons complete, take notes and track your progress.