Payment System Architecture: Idempotency, Payment States, Webhooks, Ledgers, and Reconciliation
Payment backends must be designed around one uncomfortable reality: a timeout does not tell you whether money moved.
One Business Payment Needs One Stable Identity
Create a stable payment/order attempt ID and reuse it across retries. Payment providers such as Stripe recommend idempotency keys and one PaymentIntent-style object per purchase flow to avoid creating duplicate payment attempts accidentally.
Do not interpret a client retry as a new charge automatically.
Model Payment State Explicitly
Payments are not just paid=true.
Typical states include:
created
requires_action
processing
authorized
captured
failed
cancelled
refunded
Some payment methods remain asynchronous for seconds or days, so the backend must tolerate intermediate states.
Treat Webhooks as Authoritative Asynchronous Signals
A browser can close after a payment succeeds. Fulfillment should not depend on the success page running correctly.
Verify webhook signatures, store/process event IDs idempotently, and use webhook events to reconcile provider state with your backend.
Keep Financial History Auditable
Do not overwrite away important money movements. Record immutable/auditable transaction or ledger entries for captures, refunds, fees, credits, and adjustments according to the accounting model.
A derived current_balance can be cached/materialized, but the underlying money history should remain explainable.
Separate Payment Completion From Slow Side Effects
After durable payment confirmation:
payment committed
→ publish/queue fulfillment
→ receipt
→ analytics
→ notifications
Use reliable event publication such as an outbox when losing the post-payment event would create inconsistent business state.
Reconcile Regularly
Webhooks can be delayed, retried, or temporarily fail. Periodically compare internal payment/order records with provider settlement/transaction state and investigate mismatches.
Reconciliation catches errors that realtime request handling cannot guarantee away.
Final Takeaway
Payment systems need stable idempotent identities, explicit state machines, verified asynchronous webhooks, auditable money records, reliable downstream events, and reconciliation. Never treat a network timeout or browser redirect as proof that money did—or did not—move.
References
BUILDING A SAAS PRODUCT?
Explore Lofingo’s end-to-end SaaS platforms, multi-tenant cloud architecture, and high-concurrency backend engineering.
EXPLORE SAAS SERVICES →