Design a Payment System, stage 12 of 13: change it
100x volume and a second provider
The patterns hold. The question is what new pressure appears, and which tempting shortcuts would break the guarantees.
System so far· 8 parts
Select a component to see what it is responsible for and which state it owns.
- 1Buyer's browser → Payment provider: Card entry and 3-D Secure in hosted fields
- 2Buyer's browser → Checkout API: Pay (Idempotency-Key header); poll status
- 3Checkout API → Payment provider: Create payment with the attempt's key
- 4Checkout API → Postgres: Claim attempt; conditional transitions
- 5Payment provider → Webhook receiver: Signed events: at least once, unordered
- 6Webhook receiver → Postgres: Dedupe by event id; forward-only transition
- 7Fulfillment worker → Postgres: Claim outbox rows; record completion
- 8Fulfillment worker → Email provider: Send receipt with idempotency key
- 9Reconciler → Postgres: Attempts processing too long; ledger
- 10Reconciler → Payment provider: Look up by reference; settlement report
- Request / response
- Asynchronous
What you need to know
0 of 2 checks done
Work it out
Flash sales reach 5,000 orders a minute. About how many create-payment requests a second is that?During a provider brownout, retries arrive exactly when the provider can least absorb them, and they use up your own rate limit. Bound them: exponential backoff with jitter, a retry budget, and a circuit breaker that stops new charges and tells buyers clearly. See Retries, backoff and jitter.
Check
Provider A times out on a charge. Is it safe to immediately retry the same charge with provider B?