Design a Stock Trading Platform

Design a stock trading platform like NYSE, Nasdaq, or a brokerage like Robinhood. This problem is notable for its extreme latency requirements, the criticality of correctness (a bug means real money is lost), and the specialized infrastructure built around the matching engine.

Requirements Clarification

  • Order types: Market orders (execute immediately at best price), limit orders (execute only at specified price or better), stop-loss, stop-limit.
  • Scale: NYSE processes ~6 billion shares per day, peaks at ~10 million messages/sec during volatile markets.
  • Latency: Exchange matching engines target microsecond latency. Brokerage-to-exchange round trip: <1ms for co-located systems.
  • Correctness: Orders must execute exactly once. No duplicate fills, no lost orders. Every transaction must be auditable.
  • Market data: Real-time price feed (Level 1: best bid/ask; Level 2: full order book depth) to all subscribers.

Clarify scope immediately: are you designing the exchange (matching engine, order book), the brokerage (order routing, portfolio management), or both? Most interview questions target the brokerage layer with the matching engine as a downstream dependency.

Back-of-Envelope

  • 10M messages/sec peak → 10 microseconds per message budget (latency-critical path)
  • Order book: ~10K listed securities, each with hundreds of price levels → ~100MB in memory, trivially fits on one machine
  • Market data feed: 10M messages/sec × 100 bytes = 1GB/sec — requires multicast UDP, not TCP
  • Settlement: T+2 for equities (trade clears 2 business days later via DTCC)

Core Components

Client App → Order Gateway → Risk Engine → Order Router
                                               ↓
                                        Matching Engine
                                               ↓
                               Trade Execution → Settlement Service
                                               ↓
                                       Market Data Publisher → Subscribers

The Order Book

The order book maintains all outstanding limit orders for a security, organized by price level:

AAPL Order Book (snapshot):
BIDS (buyers)              ASKS (sellers)
Price   | Qty              Price   | Qty
$189.50 | 1,200            $189.55 | 800
$189.49 | 3,400            $189.56 | 2,100
$189.48 | 500              $189.60 | 5,000

The spread is $189.55 – $189.50 = $0.05. A market buy order will execute against the best ask ($189.55).

Data structure: a sorted map (Red-Black tree or skip list) of price → queue of orders at that price. Price levels are sorted: bids descending, asks ascending. Within each price level, orders execute in FIFO order (price-time priority — standard for US exchanges).

from sortedcontainers import SortedDict
from collections import deque

class OrderBook:
    def __init__(self, symbol):
        self.symbol = symbol
        self.bids = SortedDict(lambda x: -x)  # highest price first
        self.asks = SortedDict()               # lowest price first

    def add_limit_order(self, order):
        book = self.bids if order.side == 'BUY' else self.asks
        if order.price not in book:
            book[order.price] = deque()
        book[order.price].append(order)

    def best_bid(self):
        return next(iter(self.bids)) if self.bids else None

    def best_ask(self):
        return next(iter(self.asks)) if self.asks else None

The Matching Engine

The matching engine is the heart of an exchange. It checks incoming orders against the book and generates trades (fills):

def match(order_book, incoming_order):
    trades = []
    if incoming_order.side == 'BUY':
        while (incoming_order.qty > 0
               and order_book.asks
               and order_book.best_ask()  0 and incoming_order.type == 'LIMIT':
        order_book.add_limit_order(incoming_order)
    return trades

The matching engine on a real exchange runs on a single thread to avoid concurrency bugs. Throughput comes from raw CPU speed, kernel bypass networking (DPDK/RDMA), and co-location (exchange servers physically next to the matching engine to minimize network latency).

Order Gateway and Risk Engine

Before an order reaches the matching engine, it passes through:

Order Gateway: Receives orders from brokers via FIX protocol (Financial Information eXchange — the standard since 1992). Validates format, assigns order IDs, timestamps with nanosecond precision (GPS-synchronized clocks). Publishes to the matching engine via low-latency message bus (LMAX Disruptor pattern — a lock-free ring buffer).

Risk Engine: Pre-trade risk checks — runs in microseconds before forwarding to matching engine:

  • Position limits: trader can’t hold more than X shares of a single stock
  • Account balance: buyer must have sufficient cash/margin
  • Circuit breakers: halt trading if price moves >5% in 5 minutes (SEC Rule 201)
  • Wash trading detection: buyer and seller can’t be the same entity

Market Data Distribution

Every fill, every order book change must be broadcast to all market participants in microseconds. TCP is too slow (connection state overhead). The solution: multicast UDP.

Multicast sends one packet to a group address — all subscribers receive it simultaneously without the sender needing to know who’s subscribed. UDP is connectionless (no handshake) and has no per-packet overhead. Packet loss is handled by subscribers requesting retransmission of specific sequence numbers.

Market data feeds are tiered:

  • SIP (Securities Information Processor): Consolidated feed aggregating all exchanges. Slower (milliseconds), available to all.
  • Direct feeds: Raw feed from each exchange. Faster (microseconds), expensive, used by HFT firms.

Brokerage Layer (Robinhood-style)

Most interview questions target the brokerage, not the exchange. The brokerage sits between retail users and exchanges:

Mobile App → API Gateway (REST/WebSocket)
                ↓
        Order Management System (OMS)
                ↓
        Smart Order Router → NYSE / Nasdaq / CBOE
                ↓
        Portfolio Service → PostgreSQL (positions, cash)
                ↓
        Notification Service → WebSocket push to app

Smart Order Router (SOR): Finds the best available price across all exchanges and dark pools. Routes portions of a large order to multiple venues to minimize market impact.

Portfolio Service: Maintains real-time positions per user. On every fill, update cash balance and share count. Must be idempotent — use fill_id as idempotency key. Partition by user_id.

Latency at Each Layer

Component Latency Technique
Client → Brokerage API 50–200ms Internet + TLS
Brokerage → Exchange 1–5ms Leased line or co-location
Exchange Order Gateway 10–100µs Kernel bypass (DPDK), FIX
Matching Engine 1–10µs Single-threaded, in-memory, LMAX Disruptor
Market Data Publish 1–5µs Multicast UDP

Interview Follow-ups

  • How do you implement a trading halt? When the matching engine stops, how do queued orders resume without a price gap?
  • How do you handle the opening auction — matching all pre-market orders at a single opening price?
  • Design the settlement layer: how does DTCC guarantee that shares and cash transfer atomically across brokerages?
  • How do you handle partial fills? A limit buy for 1,000 shares fills 400 now. What happens to the remaining 600?
  • What are the consistency requirements between the order book (in-memory) and the trade ledger (persistent DB) if the matching engine crashes?

Related System Design Topics

  • Design a Payment System — idempotency, double-entry bookkeeping, and settlement apply directly to trade clearing and portfolio updates
  • Message Queues — LMAX Disruptor (lock-free ring buffer) is a specialized queue pattern at the core of matching engine throughput
  • Design a Distributed Key-Value Store — the order book is an in-memory key-value structure optimized for microsecond access
  • SQL vs NoSQL — trade ledger requires ACID (relational); market data tick store uses time-series DB (InfluxDB, kdb+)
Scroll to Top