Skip to content

Design a Payment System, stage 3 of 13: decide

Where does payment state live?

A buyer may try one card, get declined, and pay with another. A payment may sit in "processing" for minutes. Finance needs to know exactly which provider event made an order paid, and support needs to answer "why was I charged?" months later.

System so far· 4 parts
12CLIENTBuyer's browserSERVICECheckout APIDATABASEPostgresEXTERNALPayment provider

Select a component to see what it is responsible for and which state it owns.

  1. 1Buyer's browser → Payment provider: Card entry and 3-D Secure in hosted fields
  2. 2Buyer's browser → Checkout API: Pay (Idempotency-Key header); poll status

What you need to know

0 of 2 checks done
  1. A boolean can say "paid" or "not paid". A payment can be in more states than that: we asked and don't know yet, declined (with a reason), succeeded, refunded. And one order can have several attempts: a declined card, then a different card.

    A model with too few states forces you to guess whenever reality is in a state you can't represent.

  2. Check

    Payment state is a 'paid' boolean on the order. The provider call times out. What do you store?