PrepZone Logo
PrepZone

E-Commerce Platform

Catalog, cart, checkout, inventory and order fulfilment for an Amazon-scale marketplace.

Read these first

Design StreamShop — StreamHub's marketplace for creator merchandise: browse products, add to cart, checkout with payment, and track order fulfilment. Amazon-scale patterns at StreamHub's 50M buyer audience.

Requirements

Functional requirements

  • Product catalog: browse, search, filter by creator/category/price.
  • Shopping cart: add/remove items; persist across sessions.
  • Checkout: shipping address, payment, order confirmation.
  • Inventory management: track stock; prevent overselling.
  • Order tracking: status updates (placed, shipped, delivered).
  • Seller dashboard: list products, manage inventory, view orders.

Non-functional requirements

  • Scale: 50M buyers; 500K sellers; 10M products; 1M orders/day.
  • Checkout latency: Under 3 seconds end-to-end.
  • Inventory accuracy: Zero overselling — strong consistency on stock decrements.
  • Payment reliability: Exactly-once charge via idempotency keys.
  • Availability: 99.99% for browse; 99.9% for checkout (graceful degradation).

Out of scope: Recommendation engine, auction/bidding, international customs/tax calculation.

Estimation

  • 1M orders/day × 3 items avg = 3M order line items/day.
  • 50M buyers × 5 cart items avg × 200 bytes = 50 GB cart storage — Redis with Postgres backup.
  • Product catalog: 10M products × 2 KB metadata = 20 GB — Elasticsearch for search, Postgres for transactional.
  • Order storage: 1M/day × 365 × 1 KB = 365 GB/year — partition by date, archive after 2 years.
  • Payment: 1M transactions/day ≈ 12 QPS average — Stripe handles scale; focus on idempotency.

StreamShop e-commerce architecture

CLIENT
Buyersweb + mobile
NETWORK
CloudFront …API Gateway
COMPUTE
CheckoutStripe + idem…
ANALYTICS
Catalog APIOpenSearch
DATABASE
Cart svcElastiCache
DATABASE
RDS invento…strong consis…
INTEGRATION
MSK ordersfulfilment ev…
COMPUTE
SQS workersship · email
Browse → cart (Redis) → checkout (idempotent) → inventory → MSK fulfilment.

API design

Java
GET  /v1/products?query=hoodie&creator=sh_4420&page=1
GET  /v1/products/{id}
POST /v1/cart/items:       { "product_id": "p_123", "quantity": 2 }
GET  /v1/cart
POST /v1/checkout:
  headers: { Idempotency-Key: "uuid" }
  body: { "shipping_address": {...}, "payment_method_id": "pm_abc" }
GET  /v1/orders/{id}
GET  /v1/sellers/me/orders?status=pending
PATCH /v1/sellers/me/products/{id}/inventory: { "quantity": 50 }
Java
CREATE TABLE products (
    id          BIGINT PRIMARY KEY,
    seller_id   BIGINT NOT NULL,
    title       VARCHAR(256) NOT NULL,
    price_cents INT NOT NULL,
    inventory   INT NOT NULL DEFAULT 0,
    status      VARCHAR(16) DEFAULT 'active'
);

CREATE TABLE orders (
    id              BIGINT PRIMARY KEY,
    buyer_id        BIGINT NOT NULL,
    status          VARCHAR(16) NOT NULL,
    total_cents     INT NOT NULL,
    shipping_addr   JSONB,
    payment_id      VARCHAR(64),
    created_at      TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE order_items (
    order_id    BIGINT NOT NULL,
    product_id  BIGINT NOT NULL,
    quantity    INT NOT NULL,
    price_cents INT NOT NULL,
    PRIMARY KEY (order_id, product_id)
);

CREATE TABLE carts (
    user_id     BIGINT NOT NULL,
    product_id  BIGINT NOT NULL,
    quantity    INT NOT NULL,
    updated_at  TIMESTAMPTZ DEFAULT now(),
    PRIMARY KEY (user_id, product_id)
);

High-level architecture

Services

  • Catalog service: Product CRUD; Elasticsearch for search; Postgres as source of truth.
  • Cart service: Redis for active carts (fast reads); async persist to Postgres.
  • Order service: Orchestrates checkout saga — inventory, payment, order creation.
  • Inventory service: Atomic stock decrements with optimistic or pessimistic locking.
  • Payment service: Stripe integration with idempotency keys; webhook for confirmation.
  • Fulfilment service: Kafka consumer updates order status; notifies buyer via notification system.

Deep dive: inventory consistency

AspectOptimistic locking (version column)Pessimistic locking (SELECT FOR UPDATE)
MechanismUPDATE WHERE version = N; retry on conflictLock row during transaction
ThroughputHigh — no locks heldLower — locks block concurrent buyers
Oversell riskZero if retry logic is correctZero if lock held until commit
StreamHub pickDefault for most productsFlash sales with extreme contention
  • Mechanism

    Optimistic locking (version column)UPDATE WHERE version = N; retry on conflict
    Pessimistic locking (SELECT FOR UPDATE)Lock row during transaction
  • Throughput

    Optimistic locking (version column)High — no locks held
    Pessimistic locking (SELECT FOR UPDATE)Lower — locks block concurrent buyers
  • Oversell risk

    Optimistic locking (version column)Zero if retry logic is correct
    Pessimistic locking (SELECT FOR UPDATE)Zero if lock held until commit
  • StreamHub pick

    Optimistic locking (version column)Default for most products
    Pessimistic locking (SELECT FOR UPDATE)Flash sales with extreme contention
Java
-- Optimistic inventory decrement
UPDATE products
SET inventory = inventory - 1, version = version + 1
WHERE id = 123 AND inventory > 0 AND version = 7;
-- If rows affected = 0 → out of stock or concurrent conflict → retry or fail

Deep dive: checkout saga

Saga steps with compensations

  • Step 1: Reserve inventory (decrement stock) — compensate: increment stock back.
  • Step 2: Charge payment via Stripe with idempotency key — compensate: refund.
  • Step 3: Create order record in Postgres — compensate: mark order cancelled.
  • Step 4: Publish order.placed to Kafka — fulfilment, notification, analytics consume.
  • Failure at any step: Run compensations in reverse order; return clear error to buyer.

Quick recall

Everything you need if you only revisit this box.

  • Catalog in Postgres + Elasticsearch; cart in Redis with Postgres backup.
  • Checkout saga: reserve inventory → charge payment → create order → publish event.
  • Optimistic locking (version column) prevents overselling without row-level locks.
  • Idempotency-Key on checkout POST prevents double-charge on retry.
  • Compensating transactions on saga failure: restock, refund, cancel order.
  • 1M orders/day ≈ 12 QPS — Postgres handles this; inventory locking is the bottleneck.

Test yourself

Answer these before moving on — recall is what makes it stick.