Shopping cart and checkout design
Designing e-commerce carts and checkout: cart storage for guests and signed-in users, merging carts, pricing and promotions, tax and shipping, inventory reservation, the checkout state machine, payment integration, order creation, idempotency and handling failures and abandonment.
Reading is half of it. See this used in a real interview: walk through Design a Payment System →
"Design Amazon's shopping cart" or "design checkout" combines several classic problems: state that must survive across devices, prices that change, inventory that runs out, payments that fail halfway, and users who retry. It is one of the most common e-commerce interview questions, and the same structure appears in food delivery, ticketing and travel bookings. This guide walks through the parts and the failure handling that makes them correct.
The cart
The cart is a user's working list: items, quantities, selected options. Requirements: fast reads and writes, durability across sessions and devices, and tolerance of high write rates during sales.
- Signed-in users: store the cart server-side, keyed by user id, in a key-value or document store (a cart is read and written as a whole). See data modelling for Cassandra and DynamoDB.
- Guests: store by an anonymous cart id in a cookie, server-side, or in the browser for very simple sites.
- Merging: when a guest signs in, merge the guest cart into the user's cart with clear rules (sum quantities, keep the latest selection).
- What to store: product ids, variant ids and quantities, plus the price seen when added (for showing changes), not the authoritative price.
- Expiry: guest carts expire after weeks; signed-in carts persist longer.
Availability matters more than strict consistency here: if two devices update the cart at once, a merge (union of items) is better than losing either change. Amazon's Dynamo paper used the shopping cart as its example for exactly this reason. See quorums and leaderless replication.
Pricing
Prices shown in the cart are a preview. At checkout, the pricing service computes the authoritative total:
- Base prices (possibly per region, currency and customer segment).
- Promotions and coupons: rules evaluated in a defined order, with limits (one per customer, usage caps tracked atomically).
- Shipping by destination, weight and speed.
- Tax by jurisdiction, often via a tax service.
The result is a quote with an id and expiry, so the price the user confirms is the price charged. If prices changed since the cart was built, show the difference before payment. See surge and dynamic pricing for the quote pattern.
Represent money as integers in minor units (cents) with a currency code, never floating point. See payments and ledgers.
Inventory
Adding to the cart usually does not reserve stock (most carts are abandoned). Stock is checked at add time for display, and reserved at checkout with a short-lived hold:
- Atomic conditional decrement of available stock, or a reservation record with expiry.
- Holds released if payment fails or the timer expires.
- High-demand items may need queueing or bucketed inventory. See inventory and flash sales.
The checkout state machine
Model checkout as explicit states, persisted, so every failure has a defined next step:
created: quote and address confirmed.inventory_reserved: holds placed.payment_authorized: card authorised (funds held, not captured).order_placed: order record created, confirmation shown.captured: payment captured when the order ships (or immediately for digital goods).
Failures move to compensating states: payment declined releases holds; inventory failure voids the authorisation. This is a saga, ideally run as a durable workflow. See workflow orchestration and distributed transactions and idempotency.
Idempotency everywhere
Users double-click "Place order", networks time out, and clients retry:
- The client sends an idempotency key per checkout attempt; the server creates at most one order per key. See idempotency keys in practice.
- Calls to the payment provider carry their own idempotency keys.
- The order id is generated once and reused across retries.
After the order
The order service writes the order and an outbox event in one transaction; downstream consumers handle fulfilment, emails, loyalty points, analytics and search updates asynchronously. See event-driven architecture and sync vs async communication.
Failure cases to mention
- Payment succeeds but the order write fails: the workflow retries the write using the same order id, or refunds automatically after a timeout. Reconcile payments against orders daily.
- Payment status unknown (timeout): query the provider with the idempotency key before retrying.
- Inventory oversold anyway (concurrent channels): backorder or cancel with apology, according to policy.
- Price or coupon changed during checkout: the quote's expiry forces a re-quote.
Scale and peaks
Sales events multiply traffic. Cache product and price data aggressively for browsing, protect checkout with queues and rate limits, pre-scale for known events, and degrade non-essential features (recommendations) first. See load shedding and backpressure.
Abandonment
Track carts that do not convert; reminder emails or pushes after a delay (with consent) recover revenue. See sending email at scale.
In the interview
"Carts live in a key-value store keyed by user or guest id, merged on login. Checkout gets an authoritative quote with an expiry, reserves inventory with a timed hold, authorises payment with an idempotency key, and creates the order in a persisted state machine run as a saga, with compensations on each failure. Order events drive fulfilment and notifications asynchronously; payments and orders are reconciled daily." The same flow fits Design Ticketmaster, Design DoorDash and Design Airbnb.
Checklist
- Cart storage for users and guests, with merge on login.
- Authoritative pricing at checkout as an expiring quote; integer money.
- Inventory reserved at checkout with expiring holds.
- Persisted checkout state machine with compensations.
- Idempotency keys for orders and payment calls.
- Outbox events for fulfilment and notifications; daily reconciliation.
- Peak protection and abandonment recovery.