Start here. This is the direct spoken answer to practice first.
Why this question matters
Checkout is a classic backend design because correctness matters more than returning quickly. The design needs to survive retries, timeouts, partial failures, and external payment side effects.
I would require an idempotency key for checkout requests and store the key with the user, request hash, order id, status, and response outcome. If the client retries with the same key, the API returns the existing result instead of creating a second order. Order creation and payment intent state would be persisted with clear states like pending, payment_authorized, confirmed, failed, and cancelled. The client gets a stable response even when the first request timed out.