System Design Interview: Design a Stock Exchange / Trading System

What Is a Stock Exchange System?

A stock exchange matching engine pairs buy and sell orders in real time, executing trades at the best available price. Core requirements: strict price-time priority (FIFO at each price level), sub-millisecond matching latency, full audit trail, and deterministic replay. NYSE and NASDAQ process 8–10 billion shares per day; modern exchanges target single-digit microsecond matching latency.

  • Netflix Interview Guide
  • Uber Interview Guide
  • LinkedIn Interview Guide
  • Databricks Interview Guide
  • Stripe Interview Guide
  • Coinbase Interview Guide
  • Order Types

    • Market order: execute immediately at best available price
    • Limit order: execute only at specified price or better
    • Stop order: becomes a market order when a trigger price is reached
    • IOC (Immediate or Cancel): fill as much as possible immediately, cancel remainder
    • FOK (Fill or Kill): fill entire order immediately or cancel entirely

    Order Book Data Structure

    The order book maintains all outstanding limit orders organized by price level. Two sides:

    • Bids: buy orders, sorted by price descending (best bid = highest price buyer will pay)
    • Asks: sell orders, sorted by price ascending (best ask = lowest price seller will accept)

    Data structure: price-level map using a sorted structure (TreeMap / SortedDict) keyed by price. Each price level holds a queue (FIFO) of orders. Operations:

    add_order(order)       → O(log P)   # P = number of price levels
    cancel_order(order_id) → O(1)       # with order_id → order pointer map
    match_order(order)     → O(M log P) # M = number of fills
    

    Matching Algorithm

    Price-time priority (most common): orders at better prices fill first; at the same price, earlier orders fill first.

    def match(incoming_buy_order, asks):
        while incoming_buy_order.qty > 0 and asks:
            best_ask_price, best_ask_queue = asks.peekmin()
            if incoming_buy_order.price  0:
            add to bids[incoming_buy_order.price]
    

    Performance Optimizations

    For sub-millisecond latency:

    • CPU pinning: matching engine thread pinned to a dedicated CPU core — no context switching
    • DPDK networking: bypass kernel network stack, process packets directly in userspace
    • Lock-free data structures: SPSC (single-producer, single-consumer) ring buffers for order ingestion
    • Memory pre-allocation: object pool for Order structs — no GC pauses (Java GC is a killer), use C++ or Rust
    • Cache locality: order book stored in contiguous memory; L1 cache hit vs. heap allocation matters at microsecond latency

    Trade Matching Log and Replay

    Every order event (submit, cancel, modify, fill) is appended to an immutable trade log (journal). The journal is the single source of truth. The in-memory order book is derived state — it can be fully reconstructed by replaying the journal from the beginning. Benefits: disaster recovery (rebuild from log), audit compliance (full history), and deterministic simulation (backtest by replaying historical order flow).

    Market Data Distribution

    After each match, the exchange broadcasts market data: Level 1 (best bid/ask), Level 2 (full order book depth), and time-and-sales (trade tape). Disseminated via multicast UDP to market data subscribers. UDP used (not TCP) because packet loss is preferable to latency — recipients request retransmission or use sequence number gaps to detect missed data.

    Interview Framework

    1. Order book: TreeMap of price levels, each level is a FIFO queue
    2. Matching: price-time priority, greedy match against opposite side
    3. Durability: append-only journal before modifying in-memory book
    4. Latency: single-threaded matching, CPU pinning, kernel bypass
    5. Market data: multicast UDP broadcast of level 1/2 and trades
    Scroll to Top