Payment states as a lifecycle, not a boolean
"Is this paid?" sounds like a yes/no question. In practice a payment moves through several distinct, meaningfully different states, and collapsing them into a single boolean throws away information a real system needs.
3 min read
The states, and what each one actually means
PENDING - payment initiated, no result yet (customer is on the
checkout page, or a bank transfer hasn't cleared)
AUTHORIZED - the issuing bank has approved and reserved the funds,
but the merchant hasn't collected them yet
CAPTURED - the merchant has actually collected the authorized
funds. Often called "settled" once money movement
between banks is fully complete.
FAILED - the attempt was declined or errored out
REFUNDED - money that was captured has been returned, in full
or in part
DISPUTED - the cardholder or issuing bank has formally contested
the charge (a chargeback)
A single isPaid: boolean column can represent at most two of these — everything else gets silently squashed into "not paid," even though AUTHORIZED, FAILED, and DISPUTED are operationally very different situations that call for very different responses.
Why "authorized" and "captured" are genuinely different moments
Many payment flows separate authorization (confirming the customer's card is good for the amount, and reserving those funds) from capture (actually pulling the money). A hotel that authorizes a card at check-in but only captures the final amount at checkout is doing exactly this, deliberately — reserving funds without charging until the true total is known. Treating "authorized" as equivalent to "paid" would let a merchant ship a product or grant access before money has actually changed hands, which is exactly backwards from what the state is telling them.
Why "refunded" isn't the opposite of "paid"
A refund doesn't undo the original charge — it's a new, separate transaction that returns money, layered on top of a payment that genuinely did complete. A record that only tracks PAID / NOT PAID has no way to represent "this succeeded, and was later reversed" versus "this simply never succeeded" — two states with very different implications for accounting (covered later in this domain) and for customer support.
A state diagram worth internalizing
Not every gateway or payment method exposes every one of these states explicitly — some collapse authorize+capture into one step for simple card charges — but the underlying lifecycle is present in essentially every real payment system, even when a specific API hides some of the transitions.
The practical implication for a data model
A payment/order record should store an actual status field with these (or similar) named states — not a boolean, and not a loosely-typed free string either, but an enum with a fixed, known set of values the rest of the codebase can exhaustively handle. Each webhook event received (covered in earlier lessons) should be read as "transition this record to state X," not "set a flag to true."
enum PaymentStatus {
PENDING = "PENDING",
AUTHORIZED = "AUTHORIZED",
CAPTURED = "CAPTURED",
FAILED = "FAILED",
REFUNDED = "REFUNDED",
DISPUTED = "DISPUTED",
}Further reading
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. A hotel authorizes a guest's card at check-in for an estimated amount, then captures the actual final total at checkout. What does treating "authorized" as equivalent to "paid" get wrong?
2. A system uses a single isPaid boolean column for orders. A payment is captured, then later refunded. What can this system NOT represent?
3. Why is a refund modeled as a new, separate transaction rather than a reversal of the original payment record?
4. What's the recommended way to model a payment's status in a database, per this lesson?