Question Breakdowns

Stock Trading

A worked system design: accept buy/sell orders and match them in a central order book with correctness and very low latency. The matching engine, sequencing, durability, and market-data fan-out.


A stock trading system accepts buy and sell orders and matches them against a central order book, executing trades at agreed prices. It's unusual in this track because the dominant constraints are extreme low latency and absolute correctness on a single hot data structure — the order book — where money is at stake on every operation. The design wisdom here is often the opposite of "scale horizontally": you make one engine deterministic and blisteringly fast. It draws on Dealing with Contention and Real-time Updates.

1. Requirements

Functional:

  • Place/cancel limit and market orders for a symbol.
  • Match opposing orders per price-time priority; execute trades.
  • Broadcast market data (order book changes, trades) to participants.

Non-functional:

  • Very low latency — microseconds matter; this is the defining constraint.
  • Correct & fair — deterministic matching, strict price-time priority, no lost/duplicated orders.
  • Durable & auditable — every order and trade is recorded; fully reconstructible.
  • Available — the exchange cannot silently lose state on failure.

2. The order book

Per symbol, an order book holds resting buy orders (bids) and sell orders (asks), each sorted by price, then time (price-time priority). Matching is: an incoming order crosses the book — a buy at or above the best ask trades immediately; otherwise it rests. The book is typically two price-sorted structures (best bid / best ask at the front) so the top of book is O(1) and matching walks price levels.

incoming buy @ 101  vs  asks: [100 x50, 101 x30, 102 ...]
  → matches 100 x50, then 101 x30 → trades execute; remainder rests as a bid

3. The counter-intuitive core: a single-threaded engine

The matching engine for a symbol is usually a single in-memory thread processing one ordered stream of events. Why not distribute it? Because matching must be deterministic and strictly ordered — price-time priority is meaningless if two threads race on the same book. A single thread over an in-memory book:

  • Removes all locking/contention — there's one writer, so no races (Dealing with Contention by serialization, the strongest form).
  • Is astonishingly fast — millions of orders/sec in RAM with no coordination overhead.
  • Is deterministic — replaying the same input sequence yields the identical book.

You scale by partitioning symbols across engines (AAPL on one, TSLA on another), not by splitting one symbol's book. Each symbol is independent, so this shards cleanly.

4. Sequencing and durability

Orders arrive from many gateways but must hit the engine in one agreed order. A sequencer assigns a monotonic sequence number to every inbound event, producing the single ordered input stream the engine consumes. That sequenced stream is written to a durable append-only log before matching (Kafka-like, or a specialized journal):

orders → sequencer (assign seq #) → durable log → matching engine (in-memory) → trades → log

Because the log is the authoritative ordered input and the engine is deterministic, recovery is replay: on crash, rebuild the in-memory book by replaying the log. This is event sourcing — the log is the source of truth, the in-memory book is a derived view. Hot standbys consume the same log in lockstep for instant failover.

5. Market data fan-out

Every participant wants live book/trade updates — a massive real-time broadcast. Keep it off the matching hot path: the engine emits an event stream of changes, and a separate market-data distribution tier fans it out to all subscribers. The engine never waits on slow consumers — matching stays fast; distribution scales independently.

6. Deep dives

  • Latency engineering: co-location, kernel-bypass networking, pre-allocated memory, no GC pauses on the hot path — the matching thread does nothing but match.
  • Order types: market/limit/stop/cancel all reduce to events applied to the book in sequence.
  • Fairness/audit: the sequenced log is the audit trail — every decision reconstructible, which regulators require.
  • Risk checks: pre-trade risk/credit checks happen at the gateway before sequencing, not in the matching thread.

What to emphasise

Flip the usual instinct — serialize, don't distribute, the book — and lean on the log:

"The constraints are microsecond latency and perfect, fair ordering on one hot structure, the order book. So counter to the usual 'scale out,' I'd run a single-threaded in-memory matching engine per symbol: one writer means no locks, no races, deterministic price-time matching, and millions of orders a second. I scale by partitioning symbols across engines, not by splitting a book. A sequencer assigns a global order to inbound events and writes them to a durable append-only log before matching, so the engine is deterministic and recovery is just replaying the log — with hot standbys consuming it in lockstep for failover. Market-data fan-out runs on a separate tier so slow subscribers never touch the matching hot path."


Next up: Collaborative Docs — concurrent editing without conflicts.