Every developer thinks they can build a payment system. Store a card, charge it, done.
Until money vanishes at 2 AM and nobody can tell you where it went.
Marketplace app. Stripe integration. Buyer pays, seller gets paid, we take a cut.
First week: customer charged twice. Request timed out, code retried, Stripe processed both. $240 gone.
Added idempotency key. Problem solved, right?
Two weeks later: seller didn't get paid. Rounding error in the split logic—$49.99 split three ways left a penny floating. 10,000 transactions later, that's real money nobody could account for.
User pays $100. Platform takes 10%, seller gets 90%. Simple, right?
But $99.99 splits differently. Platform fee is $9.999—rounds to $10.00. Seller gets $89.991—rounds to $89.99. That's a missing penny per transaction. Ten thousand transactions later, you have $100 that nobody can explain.
Idempotency. Network times out. Did the charge go through? Without an idempotency key, you might double-charge or give away free stuff. First request charges $50, times out but Stripe processed it. Retry charges another $50. Customer paid twice.
Tokenization. Never see a credit card number. Not in logs, not in your database.
Split disbursement. Money doesn't just move from A to B. It's A to B, C, and D—platform fee, tax, driver cut.
You need your own ledger. Every transaction, every split, every refund.
Your ledger says: Order 123, total $100, fee $10, payout $90, status completed.
Stripe's record says: pi_abc123, amount $100, fee $10, transfer $90, status succeeded.
Reconcile daily. Catch mismatches before they compound.
Uber processes 30 million transactions daily and reconciles constantly. If Uber doesn't trust Stripe to be the source of truth, neither should you.
Treat payments like they're someone else's money. Because they are.
— blanho
You have 10 million saved searches. A new item comes in. How do you find all matches without running 10 million queries?
The hidden state in your servers is why you can't just 'add more boxes'.
High throughput doesn't mean low latency. Often it means the opposite.
# The bug
def charge_customer(amount):
try:
stripe.PaymentIntent.create(amount=amount) # Times out
except Timeout:
stripe.PaymentIntent.create(amount=amount) # Retries. Oops.# The fix
def charge_customer(amount, order_id):
stripe.PaymentIntent.create(
amount=amount,
idempotency_key=f"order_{order_id}" # Same key = same charge
)# Never do this
card_number = request.json['card']
log.info(f"Charging card {card_number}") # PCI violation
# Do this
token = stripe.Token.create(card=request.json['card'])
log.info(f"Charging token {token.id}") # Safe# Use integers (cents), not floats
total_cents = 4999 # $49.99
platform_fee = total_cents * 10 // 100 # 499 cents
seller_amount = total_cents - platform_fee # 4500 cents
# Never: total * 0.10 (float math = rounding bugs)