Build a Distributed Shopping Cart with Guest Session Merge


distributed-systems scalability databases

System Design Deep Dive

Distributed Shopping Cart with Session Merge

Merging guest and authenticated cart state without losing items or creating duplicates at 50K RPS

⏱ 14 min read 📐 Advanced 🏗️ Shopping-Cart

Think of a shopping cart like a physical basket at a supermarket. When you walk in without a loyalty card, you still get a basket and fill it with items. The moment you swipe your card at checkout, the cashier needs to reconcile your basket with any pending online order on your account. That reconciliation is instantaneous, automatic, and must never drop your avocados. Now imagine 50,000 shoppers doing this simultaneously, from 15 different countries, on devices ranging from a 2017 Android to a MacBook Pro - and the “cashier” is a distributed cluster with no single node that knows the full picture.

A naive implementation stores the cart in the server session: session["cart"] = [...]. This works at 100 requests per second on a single box. At 50,000 RPS across 20 application servers, you have no session affinity guarantee. Every request may hit a different server, each carrying a stale or empty cart. Sticky sessions feel like a solution - pin each user to one server. But a server restart or autoscale event wipes your cart silently. Amazon discovered this the hard way in the early 2000s: session-affinity-based carts lost millions of dollars in abandoned items every week during holiday traffic spikes.

The guest-to-authenticated merge problem adds another layer of complexity. A guest user (identified by a browser fingerprint or anonymous session_id) builds a cart over multiple days - 7 items, 3 sessions, 2 devices. When they finally sign in, we must merge that guest cart into their authenticated cart without losing items, without creating phantom duplicates if the same product appears in both carts, and without blocking the login response for more than 50ms. Worse, what if they are logged in on their phone and a guest on their laptop simultaneously, and they add to both before merging?

Cart state is fundamentally distributed state with convergence requirements. It is not a simple key-value lookup. We need to solve for durable guest cart persistence with TTL, conflict-free merge on login, concurrent modification safety, and sub-50ms read latency simultaneously. Each constraint points in a different direction, and the interesting engineering lives at those intersections.

Requirements and Constraints

Functional Requirements

  • Guest users can add, remove, and update item quantities in their cart without logging in
  • Guest cart persists across browser sessions using a fingerprint or anonymous token stored in a cookie
  • On login, guest cart merges into the authenticated user’s cart automatically
  • Merge strategy handles overlapping items (same SKU in both carts) without duplicates
  • Cart survives application server restarts, deployments, and node failures
  • Cart supports concurrent modifications from multiple devices (same user logged in on phone and laptop)
  • Each cart operation (add/remove/update) is idempotent - retries do not double-count
  • Cart items expire after 30 days for guest users (TTL-based cleanup)

Non-Functional Requirements

  • Read latency: p99 under 20ms for cart fetch
  • Write latency: p99 under 50ms for item add/update
  • Availability: 99.99% (4 nines) - cart loss directly causes revenue loss
  • Throughput: 50,000 cart operations per second at peak (Black Friday scale)
  • Scale: 200 million active guest carts, 80 million authenticated carts
  • Merge operation: complete within 200ms of login event
  • Storage: average cart holds 8 items at 500 bytes each = 4KB per cart; 280M carts = 1.1TB raw cart data
  • Concurrency: support 5 simultaneous device sessions per user with last-write-wins or union semantics

Constraints

  • We are not designing the payment or checkout system - cart is pre-checkout state only
  • Product catalog and pricing are owned by a separate service; cart stores SKU and quantity only
  • We assume cookie support is available; we do not design for cookie-blocked environments
  • Single datacenter design initially; multi-region replication is out of scope but architected for

High-Level Architecture

The cart system decomposes into six major components that each handle a distinct concern.

The Cart API Gateway is the single entry point for all cart operations. It authenticates requests, extracts the identity (guest session_id or authenticated user_id), and routes to the Cart Service. It also handles idempotency key injection for retryable operations.

The Cart Service is the core application logic layer. It owns the cart read/write operations, manages the merge workflow, and orchestrates calls to the storage tier. This is a stateless service that scales horizontally.

The Guest Cart Store is a Redis cluster holding all anonymous carts, keyed by session_id. Every entry carries a 30-day TTL. Redis is the right choice here because guest carts are ephemeral, access patterns are simple key lookups, and TTL management is native.

The Authenticated Cart Store is a Postgres cluster holding carts for logged-in users. Postgres gives us ACID transactions for the merge operation, which must be atomic: read both carts, compute union, write merged result, delete guest cart.

The Cart Event Log is an append-only Kafka topic that captures every cart mutation as an event. This is the source of truth for analytics, and it enables cart event sourcing: any cart can be reconstructed from its event history if the primary store is corrupted.

The Session Merge Service consumes login events from the auth system and triggers the merge workflow asynchronously, allowing the login API to return immediately while merge proceeds in the background within the 200ms SLA.

High-level architecture: Cart API Gateway, Cart Service, Guest Redis Store, Authenticated Postgres Store, Kafka Event Log, and Session Merge Service
Key Insight

Separating guest carts (Redis, volatile, TTL-managed) from authenticated carts (Postgres, durable, transactional) lets you optimize each store for its actual access pattern instead of forcing both onto the same system with conflicting requirements.

Guest Cart Store Design

Premium Content

Unlock the full article along with everything else in the archive — all in one place.

In-depth analysis Expert insights Full archive access
Unlock Full Article