Limited time: AI code review, hints, mock interviews, whiteboard analysis, and all Pro features are unlocked. Enroll
โฑ๏ธ 22 min read

Designing a Cart Management System (Amazon / Flipkart / JioMart)

Difficulty: Intermediate Prerequisites:Caching and Message Queues


TL;DR

A cart management system lets users add, remove, and update items before checkout. The hard parts: persisting carts across devices, handling flash sales (1M users adding the same item), merging guest carts on login, and keeping prices/stock accurate without slowing down the add-to-cart path.

flowchart LR
    USER["User Browser"]:::client
    GW["API Gateway"]:::edge
    CART["Cart Service"]:::service
    REDIS[("Redis<br/>hot carts")]:::data
    DDB[("DynamoDB<br/>durable carts")]:::data
    INV["Inventory Service"]:::service

    USER -->|"1. Add item to cart"| GW
    GW -->|"2. Forward request"| CART
    CART -->|"3. Write cart fast"| REDIS
    CART -.->|"4. Async persist"| DDB
    CART -->|"5. Check stock on read"| INV

    classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
    classDef edge fill:#1e3a5f,stroke:#60a5fa,color:#e2e8f0
    classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
    classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0
Color Layer
๐ŸŸ  Orange Clients
๐Ÿ”ต Blue Edge
๐ŸŸข Green Services
๐ŸŸฃ Purple Async / Streaming
๐ŸŸก Yellow Data
๐Ÿฉท Pink External

In 3 sentences: User adds items to cart โ†’ stored in Redis for sub-ms reads and async-backed to DynamoDB for durability. On cart view, the service enriches items with live price and stock status from downstream services. At checkout, inventory is reserved with a distributed lock to prevent overselling.


1. Understanding the Problem

A shopping cart is the bridge between browsing and buying. Every e-commerce platform needs one, and despite looking simple (just a list of items), it has to handle: millions of concurrent carts during sales, real-time stock awareness, device switching (add on phone, checkout on laptop), guest-to-login transitions, flash sales where 100K users add the same item simultaneously, and graceful degradation when downstream services (inventory, pricing) are slow or down.

Think Amazon Cart, Flipkart Cart, Myntra Bag, or Zepto Cart.


2. Naive First Cut

flowchart LR
    USER["User"]:::client
    API["Cart API"]:::service
    DB[("One Postgres DB<br/>carts table")]:::data

    USER --> API
    API --> DB

    classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
    classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
    classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0

User adds item โ†’ write a row to Postgres โ†’ read it back on cart page. Works for 100 users.

How it breaks at scale:


3. Prior Art Weโ€™re Drawing From


4. Functional Requirements

Core (Top 3)

  1. Add, remove, update items โ€” user adds an item to cart, changes quantity, or removes it. Response in <100ms.
  2. Persistent cross-device cart โ€” logged-in userโ€™s cart survives app close, device switch, and browser restart. Guest carts persist via session cookie (7-day TTL).
  3. Real-time cart enrichment โ€” when user views cart, each item shows current price, stock status (in stock / only 2 left / out of stock), and delivery estimate.

Below the Line


5. Non-Functional Requirements

Core

NFR Target
Latency Add-to-cart: P99 < 100ms. Cart page load: P99 < 200ms
Availability 99.99% โ€” cart must never be โ€œdownโ€ (itโ€™s pre-checkout, losing it = lost revenue)
Scale 50M DAU, 10M concurrent active carts, 500K add-to-cart ops/sec at peak (flash sale)
Durability Logged-in userโ€™s cart must never be lost. Acceptable: guest carts can be lost on infra failure (theyโ€™re session-tied).
Consistency Eventually consistent for cart reads (5s stale is fine). Strongly consistent for inventory reservation at checkout.

Below the Line


6. Scale Estimation (Back-of-Envelope)


7. Core Entities


8. API / System Interface

POST /v1/cart/items
  Body: { itemId, sellerId, quantity }
  Response: { cartId, items[], totalItems, version }
  Auth: JWT (logged-in) or Session cookie (guest)
  Note: Idempotent via clientRequestId header. Does NOT check inventory (fire-and-forget add).

PATCH /v1/cart/items/{itemId}
  Body: { quantity }
  Response: { cartId, items[], version }
  Note: quantity=0 is equivalent to DELETE

DELETE /v1/cart/items/{itemId}
  Response: { cartId, items[], version }

GET /v1/cart
  Response: { cartId, items[{ itemId, quantity, currentPrice, stockStatus, deliveryEstimate }], totalAmount, version }
  Note: Enriched response โ€” each item has LIVE price and stock from downstream services.
  Auth: JWT or Session cookie

POST /v1/cart/merge
  Body: { guestSessionId }
  Response: { cartId, items[], mergeConflicts[] }
  Note: Called on login. Merges guest cart into user cart.

POST /v1/cart/checkout
  Response: { orderId, reservationId, paymentUrl }
  Note: This is where inventory gets RESERVED (locked). Not before.

Security notes:


9. High-Level Design

FR1: Add / Remove / Update Items

The most frequent operation. Must be blazing fast โ€” users expect instant feedback when clicking โ€œAdd to Cart.โ€

New components:

  1. API Gateway โ€” rate limiting, auth, routing
  2. Cart Service โ€” core business logic for cart operations
  3. Redis Cluster โ€” hot cart storage. Each userโ€™s cart is a Redis Hash.
    ๐Ÿ’ก Redis Hash: HSET cart:{userId} {itemId} โ€œ{qty, sellerId, priceAtAdd, addedAt}โ€. O(1) per field operation.
  4. DynamoDB โ€” durable backup. Async write-behind from Redis.
  5. Kafka โ€” emits cart events for analytics and abandoned-cart workflows
flowchart LR
    USER["User"]:::client
    GW["API Gateway"]:::edge
    CS["Cart Service"]:::service
    REDIS[("Redis Cluster<br/>hot carts")]:::data
    DDB[("DynamoDB<br/>durable backup")]:::data
    KF["Kafka"]:::async

    USER -->|"1. POST add item"| GW
    GW -->|"2. Auth + rate limit"| CS
    CS -->|"3. HSET cart:userId"| REDIS
    CS -.->|"4. Async write-behind"| DDB
    CS -->|"5. Emit item_added event"| KF

    classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
    classDef edge fill:#1e3a5f,stroke:#60a5fa,color:#e2e8f0
    classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
    classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0
    classDef async fill:#3b1f5e,stroke:#c084fc,color:#e2e8f0

Step-by-step flow:

  1. User taps โ€œAdd to Cartโ€ for itemId=SKU_123, quantity=1
  2. Request hits API Gateway โ†’ validates JWT โ†’ extracts userId โ†’ forwards to Cart Service
  3. Cart Service executes Redis command: HSET cart:{userId} SKU_123 '{"qty":1,"seller":"seller_abc","price":499,"addedAt":"..."}'
  4. Redis responds in <1ms โ†’ Cart Service returns 200 OK to user immediately
  5. Async: Cart Service publishes to Kafka topic cart-events: {type: "ITEM_ADDED", userId, itemId, qty, timestamp}
  6. Async: A write-behind consumer reads from Kafka and persists to DynamoDB (batched, every 5s or 100 events)

Why we do NOT check inventory at add-time:


FR2: Persistent Cross-Device Cart + Guest Merge

User adds items on phone โ†’ closes app โ†’ opens laptop โ†’ cart is there. Guest browses without login โ†’ adds 3 items โ†’ logs in โ†’ those items appear in their saved cart.

New components:

  1. Session Service โ€” maps guest session cookies to temporary cart IDs in Redis
  2. Cart Merge Logic โ€” handles conflicts when guest cart and user cart have overlapping items
flowchart LR
    GUEST["Guest User"]:::client
    LOGGED["Logged-in User"]:::client
    CS["Cart Service"]:::service
    REDIS[("Redis<br/>both carts")]:::data
    MERGE["Merge Logic"]:::service

    GUEST -->|"1. Add items (session cookie)"| CS
    CS -->|"2. Write to guest cart"| REDIS
    LOGGED -->|"3. Login triggers merge"| CS
    CS -->|"4. Read guest cart"| REDIS
    CS -->|"5. Read user cart"| REDIS
    MERGE -->|"6. Merge + write final"| REDIS

    classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
    classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
    classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0

Step-by-step flow:

  1. Guest browses โ†’ session cookie assigned โ†’ cart stored at cart:guest:{sessionId} in Redis with 7-day TTL
  2. Guest adds items โ†’ same flow as FR1 but keyed by sessionId instead of userId
  3. Guest logs in โ†’ frontend calls POST /v1/cart/merge { guestSessionId }
  4. Cart Service reads both carts from Redis: guest cart + userโ€™s existing cart
  5. Merge strategy (per item):
    • Item only in guest cart โ†’ add to user cart
    • Item only in user cart โ†’ keep as-is
    • Item in both โ†’ take higher quantity (user intent: they wanted more)
  6. Write merged cart to cart:{userId}, delete cart:guest:{sessionId}
  7. Return merged cart to frontend with any conflicts highlighted

Cross-device persistence:


FR3: Real-Time Cart Enrichment (Price + Stock)

When user opens the cart page, they donโ€™t just see โ€œiPhone ร— 1.โ€ They see: current price (might have changed since they added it), stock status (โ€œonly 2 leftโ€), delivery estimate, and a warning if price increased.

New components:

  1. Inventory Service โ€” returns current stock level per item
  2. Pricing Service โ€” returns current price (may differ from price-at-add-time)
  3. Catalog Service โ€” returns item details (name, image, seller info)
flowchart LR
    USER["User opens cart"]:::client
    CS["Cart Service"]:::service
    REDIS[("Redis<br/>cart items")]:::data
    INV["Inventory Service"]:::service
    PRICE["Pricing Service"]:::service
    CAT["Catalog Service"]:::service

    USER -->|"1. GET /cart"| CS
    CS -->|"2. HGETALL cart:userId"| REDIS
    CS -->|"3. Batch stock check"| INV
    CS -->|"4. Batch price fetch"| PRICE
    CS -->|"5. Batch item details"| CAT
    CS -->|"6. Return enriched cart"| USER

    classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
    classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
    classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0

Step-by-step flow:

  1. User opens cart page โ†’ GET /v1/cart
  2. Cart Service reads raw cart from Redis: HGETALL cart:{userId} โ†’ returns {SKU_123: qty 1, SKU_456: qty 2}
  3. Cart Service calls downstream services IN PARALLEL (not sequential):
    • Inventory: POST /inventory/batch-check { itemIds: [SKU_123, SKU_456] } โ†’ {SKU_123: 15 in stock, SKU_456: 0}
    • Pricing: POST /pricing/batch { itemIds: [...] } โ†’ {SKU_123: โ‚น499 (same), SKU_456: โ‚น1299 (was โ‚น999)}
    • Catalog: POST /catalog/batch { itemIds: [...] } โ†’ {names, images, seller info}
  4. Cart Service assembles enriched response:
    {
      "items": [
        { "itemId": "SKU_123", "qty": 1, "currentPrice": 499, "priceAtAdd": 499, "stock": "IN_STOCK", "stockQty": 15 },
        { "itemId": "SKU_456", "qty": 2, "currentPrice": 1299, "priceAtAdd": 999, "stock": "OUT_OF_STOCK", "priceChanged": true }
      ]
    }
    
  5. Frontend shows: โ€œPrice increased โ‚น999 โ†’ โ‚น1299โ€ badge and โ€œOut of Stock โ€” Removeโ€ option

Graceful degradation: If inventory service is slow/down โ†’ return cart without stock info (show โ€œchecking availabilityโ€ฆโ€ on frontend). Cart should NEVER fail to load because a downstream enrichment service is down.


10. Technology Choices

Tier Purpose Stores Access Pattern Primary Alternatives
Hot cart store Active carts (session-like, fast) userId โ†’ {items} High-QPS reads + writes, sub-ms Redis Cluster Memcached, Aerospike
Durable cart store Cart backup, survives Redis failure userId โ†’ {items, metadata} Write-behind from Redis, fallback reads DynamoDB Cassandra, ScyllaDB, MongoDB
Cart events Analytics, abandoned cart triggers cart_updated, item_added events Append-only, consumed by analytics Kafka Kinesis, Pub/Sub
Inventory service Stock levels per item itemId โ†’ quantity_available High-QPS reads, strong consistency for reservation Postgres (with row locks for checkout) DynamoDB conditional writes
Pricing service Current price per item itemId โ†’ price, discounts Read-heavy, cacheable Redis cache + Postgres source Pricing microservice
Session store Guest cart โ†’ session mapping sessionId โ†’ guestCartId Short-lived, TTL-based Redis (with 7-day TTL) Cookie-only (limited)

Why Redis + DynamoDB (not just Postgres):

Cart is session-like data โ€” high write rate, high read rate, no complex joins, flexible schema (items vary per seller). Postgres row locks collapse at 500K writes/sec. Redis gives sub-ms latency for the hot path. DynamoDB provides infinite-scale durability without managing shards.


11. Data Modeling

Redis (Hot Cart Store โ€” active session carts):

Key: "cart:{userId}" โ†’ Hash
  Field: "items" โ†’ JSON [{ itemId, sellerId, quantity, priceAtAdd, addedAt }, ...]
  Field: "version" โ†’ Integer (optimistic concurrency)
  Field: "updatedAt" โ†’ Timestamp
TTL: 30 days (inactive carts expire)

DynamoDB (Durable Cart Store โ€” backup and persistence):

Table: carts
  PK: user_id (String)
  Attributes: items (List of Maps), version, updated_at, expires_at
  GSI: session_carts โ€” PK: session_id (for guest cart lookup)

Postgres (Inventory โ€” stock levels with row locks at checkout):

CREATE TABLE inventory (
    item_id UUID PRIMARY KEY,
    seller_id UUID NOT NULL,
    quantity_available INTEGER NOT NULL CHECK (quantity_available >= 0),
    reserved_quantity INTEGER NOT NULL DEFAULT 0,
    updated_at TIMESTAMP NOT NULL
);

CREATE TABLE inventory_reservations (
    reservation_id UUID PRIMARY KEY,
    cart_id UUID NOT NULL,
    item_id UUID NOT NULL,
    quantity INTEGER NOT NULL,
    status VARCHAR(10) NOT NULL,  -- HELD, CONFIRMED, RELEASED
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP NOT NULL
);
CREATE INDEX idx_reservations_expiry ON inventory_reservations(expires_at) WHERE status = 'HELD';

Access Patterns:

Query Data Source How
Add item to cart Redis HSET cart:{userId} with updated items JSON + INCR version
Read cart (enriched) Redis + Pricing/Inventory Read Redis cart โ†’ parallel calls to pricing and inventory services
Guest-to-user merge Redis + DynamoDB Read guest cart by sessionId, merge into user cart, delete guest
Reserve inventory at checkout Postgres UPDATE inventory SET reserved_quantity = reserved_quantity + ? WHERE item_id = ? AND quantity_available - reserved_quantity >= ? (row lock)
Write-behind to DynamoDB Async Kafka event on cart change โ†’ DynamoDB writer persists

How Cart-Inventory Interaction Works at Checkout:

  1. User clicks โ€œBuy Nowโ€ โ†’ Cart Service reads current cart from Redis
  2. For each item: SELECT quantity_available - reserved_quantity AS available FROM inventory WHERE item_id = ? FOR UPDATE (row-level lock)
  3. If available >= requested: INSERT INTO inventory_reservations with status=HELD and expires_at = now()+10min
  4. UPDATE inventory SET reserved_quantity += requested WHERE item_id = ?
  5. All in one Postgres transaction โ€” if ANY item is unavailable, entire txn rolls back (no partial reservations)
  6. A background sweeper releases expired reservations every minute: UPDATE ... SET status='RELEASED' WHERE expires_at < now() AND status='HELD'

12. Deep Dives

Deep Dive 1: Flash Sale โ€” 500K Users Add the Same Item Simultaneously

Problem: Big Billion Days. iPhone listed at โ‚น39,999. 500K users click โ€œAdd to Cartโ€ in the first 10 seconds. Only 1000 units available.

Bad: Check inventory on every add-to-cart. Inventory service gets 500K reads/sec for one item โ†’ hot key โ†’ collapses. Users see โ€œitem unavailableโ€ errors.

Good: Donโ€™t check inventory at add-time. Let everyone add to cart freely. Check stock only on cart page view and at checkout. Show โ€œlimited stockโ€ badge. First 1000 to checkout win.

Great: Same as Good, but add a soft limit at the cart level. After the first 2000 add-to-carts for a flash-sale item, start showing โ€œselling fast โ€” checkout nowโ€ urgency messaging. Use Redis INCR on a counter flash:{itemId}:carts to track how many carts contain this item. This doesnโ€™t block anyone but creates urgency and reduces phantom demand.

At checkout: use DynamoDB conditional write (or Postgres SELECT FOR UPDATE) to atomically decrement inventory. If inventory hits 0, reject checkout for subsequent users. Their cart still has the item, but they see โ€œsold outโ€ when they try to pay.

Key insight: Adding to cart is NOT a commitment to buy. Donโ€™t waste inventory-service capacity on something that has a 70% abandonment rate.


Deep Dive 2: Write-Behind Pattern โ€” Redis + DynamoDB Consistency

Problem: We write to Redis first (fast) and async-persist to DynamoDB (durable). What if Redis crashes after the write but before the DynamoDB persist? Userโ€™s last few cart changes are lost.

Bad: Write to DynamoDB synchronously on every cart operation. Adds 5-10ms latency to every add/remove. At 500K ops/sec, DynamoDB costs explode (on-demand pricing).

Good: Write-behind with Kafka as buffer. Cart Service writes to Redis AND publishes to Kafka. A consumer drains Kafka into DynamoDB in batches. If Redis crashes, Kafka still has the events โ†’ replay into DynamoDB โ†’ hydrate back to Redis from DynamoDB.

Great: Same as Good + version vector on the cart. Each cart has a monotonically increasing version field. Redis cart has version 47. DynamoDB has version 45 (slightly behind). On Redis failure:

  1. Cart Service falls back to reading DynamoDB (version 45)
  2. When Redis recovers, hydrate from DynamoDB
  3. If user made changes during the fallback window, those are already in DynamoDB (the consumer was writing there via Kafka)
  4. No data loss. At most 2-3 seconds of stale reads during the Redisโ†’DynamoDB switchover.

Deep Dive 3: Cart Merge Conflicts

Problem: Guest has: {iPhone: qty 2, AirPods: qty 1}. Logged-in cart has: {iPhone: qty 1, MacBook: qty 1}. User logs in. What does the merged cart look like?

Bad: Overwrite user cart with guest cart (lose MacBook). Or overwrite guest with user (lose AirPods).

Good: Union of both carts. For conflicts (same item in both), take max quantity. Result: {iPhone: 2, AirPods: 1, MacBook: 1}.

Great: Same as Good but with user transparency. Show a toast: โ€œWe added 1 item from your browsing sessionโ€ or a merge summary. For quantity conflicts, default to max but let user adjust on the cart page. Log merge events to Kafka for analytics (how many users hit merge conflicts? is it causing confusion?).

Edge case: guest cart has item thatโ€™s now out of stock. Still merge it in โ€” show โ€œout of stockโ€ badge. Donโ€™t silently drop items.


Deep Dive 4: Cart Abandonment Detection + Recovery

Problem: 70% of carts are abandoned. Can we nudge users back?

Bad: Poll the DB every hour for โ€œcarts not checked out in 24h.โ€ At 50M carts, this is expensive and wasteful.

Good: Event-driven. Kafka consumer tracks item_added events. If no checkout_initiated event arrives within 24 hours for that userId, emit an abandoned_cart event. Notification service sends push/email: โ€œYou left items in your cart.โ€

Great: Tiered nudges:

Implementation: Use a delayed Kafka consumer (or Redis sorted set with fire-time) to schedule nudge events at each tier. Cancel all pending nudges if user checks out.


Deep Dive 5: Inventory Reservation at Checkout

Problem: User has 2 iPhones in cart. They click โ€œProceed to Checkout.โ€ Between clicking and completing payment (2-5 minutes), another user could buy the last iPhone. How do we prevent overselling?

Bad: Decrement inventory on add-to-cart. 500K carts hold 500K โ€œreservationsโ€ but 70% abandon. Real customers canโ€™t buy because inventory is โ€œheldโ€ by abandoned carts.

Good: Reserve inventory only at checkout initiation (when user clicks โ€œPayโ€). Use a TTL-based hold (10 minutes). If payment isnโ€™t completed, hold releases automatically.

Great: Conditional write with fencing:

DynamoDB:
  UpdateItem(itemId=SKU_123)
  SET available = available - 2
  CONDITION: available >= 2

If condition fails (not enough stock), return โ€œonly X left, reduce quantity.โ€ The conditional write is atomic โ€” no two users can over-decrement.

TTL-based hold: write a reservation record {reservationId, itemId, qty, expiresAt: now+10min}. A sweeper restores inventory for expired reservations. Same pattern as BookMyShow seat locks.


13. Final Architecture

flowchart TD
    WEB["Web Browser"]:::client
    APP["Mobile App"]:::client

    GW["API Gateway<br/>rate limit + auth"]:::edge

    CS["Cart Service"]:::service
    INV["Inventory Service"]:::service
    PRICE["Pricing Service"]:::service
    CAT["Catalog Service"]:::service
    MERGE["Merge Handler"]:::service
    NOTIF["Notification Service"]:::service

    REDIS[("Redis Cluster<br/>hot carts")]:::data
    DDB[("DynamoDB<br/>durable carts")]:::data
    PG[("Postgres<br/>inventory")]:::data

    KF["Kafka"]:::async

    WEB --> GW
    APP --> GW
    GW --> CS
    CS --> REDIS
    CS -.-> KF
    KF -.-> DDB
    KF -.-> NOTIF
    CS --> INV
    CS --> PRICE
    CS --> CAT
    CS --> MERGE
    INV --> PG
    MERGE --> REDIS

    classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
    classDef edge fill:#1e3a5f,stroke:#60a5fa,color:#e2e8f0
    classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
    classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0
    classDef async fill:#3b1f5e,stroke:#c084fc,color:#e2e8f0

How it works end-to-end:

  1. User adds item โ†’ API Gateway authenticates and rate-limits โ†’ Cart Service writes to Redis (sub-ms)
  2. Cart event published to Kafka โ†’ consumed by DynamoDB writer (durability) and analytics pipeline
  3. User views cart โ†’ Cart Service reads from Redis + enriches in parallel from Inventory, Pricing, and Catalog services
  4. User logs in โ†’ Merge Handler combines guest cart with user cart, writes merged result to Redis
  5. User proceeds to checkout โ†’ Inventory Service reserves stock with conditional write (DynamoDB or Postgres row lock)
  6. If user abandons โ†’ Kafka-based timer fires nudge notifications at 2h, 24h, 72h intervals
  7. If Redis fails โ†’ Cart Service falls back to DynamoDB reads (slightly slower but no data loss)

Metrics to Monitor

Business Metrics

Metric What it tells you
Cart abandonment rate % of carts that never reach checkout
Cart-to-checkout conversion Funnel health
Avg items per cart Engagement signal
Time: add-to-cart โ†’ checkout Are users hesitating?
Price-change impact How many users see โ€œprice increasedโ€ and remove item?

Technical Metrics

Metric Alert threshold
Add-to-cart P99 latency >100ms
Cart read P99 latency >200ms
Redis hit rate <95%
Redis โ†’ DynamoDB sync lag >5 seconds
Inventory service P99 >50ms
Cart merge error rate >0.5%
Flash sale counter (carts holding item) Track for demand forecasting

Whatโ€™s Expected at Each Level

Mid-level

Design a basic cart with add/remove/get operations using Redis. Recognize the need for persistence beyond Redis. Propose DynamoDB or Postgres as backup. Understand why inventory shouldnโ€™t be checked at add-time.

Senior

Propose the write-behind pattern (Redis + Kafka + DynamoDB). Discuss cart merge strategies. Explain flash sale handling without blocking the add-to-cart path. Design the enrichment layer with parallel calls and graceful degradation. Discuss the checkout reservation with conditional writes.

Staff+

Discuss multi-region cart consistency, version vectors for conflict resolution, cart-level rate limiting for bot prevention during flash sales, and the abandoned-cart recovery pipeline with tiered nudges. Quantify costs (Redis cluster sizing, DynamoDB on-demand pricing). Propose observability: which metrics distinguish a healthy cart system from a degraded one.


๐ŸŽฏ Key Takeaways



Discussion

Newest first
You

Free system design + DSA prep. If it helped you crack an interview, consider supporting.

SensAI SensAI
Beta
Listening...
Tap mic to stop voice mode

Shape what we build next

Every piece of feedback is read by the team and directly influences our roadmap.

What type of feedback?

Install SystemCraft

Add to your home screen for instant access, offline reading, and a distraction-free experience.

Offline reading Faster loads No browser tabs App-like feel

Unlock AI Features

One click to activate - no payment, no credit card. Just sign in and you're in.

AI code review and hints
SensAI chat assistant
AI mock interviews
Whiteboard analysis
100% free during early access