Idempotency, a double-entry ledger, webhooks and reconciliation. Where money can go wrong and how not to lose any.
What is on this board
Parts
- Checkout Web app
- Payments API Service
- Seen keys Key-value store · Redis
- Card processor Payment provider · Stripe
- Pix Banking / open finance · Pix
- Ledger Ledger · Postgres
- Outbox Message queue
- Provider events Webhook
- Risk score Fraud detection
- Reconcile nightly Scheduled job
- Who did what Audit log
- Start Initial state
- Created State
- Authorized State
- Captured State
- Failed State
- Refunded State
- Never update a balance Decision record
How they connect
- Checkout → Payments API: pay
- Payments API → Seen keys: already done?
- Payments API → Risk score: score
- Payments API → Card processor: charge
- Payments API → Pix: or Pix
- Card processor → Provider events: succeeded
- Provider events → Payments API: update
- Payments API → Ledger: two entries
- Payments API → Outbox: paid
- Reconcile nightly → Card processor: their report
- Reconcile nightly → Ledger: our entries
- Payments API → Who did what: record
Notes and decisions
- Payments API: Every call carries an idempotency key
- Ledger: Double entry, append only
- Never update a balance: The balance is the sum of the ledger. Entries are only added, so every cent can be traced.
More like this
News feed, like TwitterFan-out on write or on read? Timelines in a cache, the celebrity problem, and how a post reaches millions of followers.
News feed, like TwitterFan-out on write or on read? Timelines in a cache, the celebrity problem, and how a post reaches millions of followers.
URL shortener, like BitlyThe first system design interview question: key generation, heavy reads, a cache in front, and click analytics off the request path.