Why a checkout flow checks its own data before calling the external payment service
Confirm the item is in stock (1), then charge the card (2), then confirm the order lines were built (3). Splitting it this way stops you from charging a customer when the order can't actually be fulfilled.
← → · Space · swipe to navigate
Is the item actually in stock? Decided at the product level — no customer involved yet. If not, stop here.
Call the payment service and charge the card. This is the moment the charge record is created.
Build the order lines for this order. If they come out empty, stop; otherwise confirm.
The charge record only exists after step 2. If the pre-check required it, every first-time checkout would see nothing and be blocked — even when the item is in stock. So the pre-check looks only at product-level stock, never at the per-order charge.
When the data is not ready, the validate-first order never calls the payment service, so there is no charge to refund. The real win is not "more checks" — it is not doing the irreversible step on bad input.
| Situation | Pre-check (stock) | Post-check (this order) | Result |
|---|---|---|---|
| In stock + already charged | pass | lines built | proceed |
| In stock + not charged yet (before step 2) | pass | none | expected — charge not made yet |
| Out of stock | block | — | no payment call |
none on the post-check — which is exactly why the pre-check must not depend on it.Generic illustrative example · built with mermaid-slide-deck (TEMPLATE.html). Numbers are made up to show the layout.