Design a Stock Exchange
Match buy and sell orders in microseconds, in a strict and provable order, never lose a fill, and stay correct when the matching engine dies mid-trade.
Last updated 2026-09-22. Difficulty: hard. Patterns: order-book, determinism, event-sourcing, low-latency, fairness. Reported at Stripe, Robinhood, Coinbase, Bloomberg, Amazon, Google.
Sit this as an AI interview and be asked it one question at a time; Study shows every answer, and Practice hides them until you have produced your own.
Functional requirements
- Accept limit and market orders. Place, cancel and replace, each acknowledged with a deterministic outcome. An acknowledgement is a promise about a position in a sequence, not a hope.
- Match by price, then time. The best price wins; at the same price the earlier order wins. This single rule is the product, and every design choice defends it.
- Publish market data. Top of book and full depth, plus a trade tape, to thousands of subscribers with identical content and no subscriber advantaged over another.
- Report fills to the owning participant. A private stream per participant carrying their own fills and order state, which must never miss an event.
- Risk checks before an order reaches the book. Credit, position and fat-finger limits. A rejected order must never touch the book, and the check must not cost the latency budget.
- Open, close, halt and replay. Auctions at the open and close, a halt on extreme moves, and the ability to reconstruct the day exactly from the log for regulators.
- Out of scope. Clearing and settlement (T+1 with a clearing house), custody of assets, market-maker incentive schemes, and the retail brokerage in front of the exchange.
Non-functional requirements
- Matching latency (p99 < 100 µs in the engine). Measured from the order entering the engine to the fill leaving it. Microseconds, not milliseconds: this is the one system in this catalogue where the units change.
- Determinism (byte-identical replay). Replaying the input log must produce exactly the same fills in the same order. Without it there is no audit, no recovery and no failover.
- Throughput (1 M orders/s peak per symbol group). The open is several times the average. Sizing for the average means failing exactly when it matters.
- Durability of the sequence (no acknowledged order lost). An order acknowledged and then forgotten is a legal problem, not an engineering one.
- Fairness (equal access, provable order). Every participant sees a change at the same moment, to within the physics. Ordering is decided in one place and is auditable afterwards.
- Availability (failover < 1 s, no lost state). A halted market is preferable to an inconsistent one, but a market that halts often is not a market anyone uses.
- Auditability (every event retained 7 years). Regulators ask what happened at a named microsecond, years later, and expect an exact answer.
Back-of-envelope estimates
- Orders per second: ~1 M/s peak. 5 000 symbols × ~200 orders/s each at the open = ~1 M/s, and the majority are cancels: a modern market is dominated by quote updates, not by trades.
- Order-to-trade ratio: ~20:1. Market makers post and pull constantly, so roughly 20 order messages per executed trade. That is why cancel latency matters as much as match latency, and why the book is mostly churn.
- Order book memory per symbol: ~5 MB. ~50 k resting orders × ~100 B (id, participant, price, quantity, timestamp, links) = ~5 MB. 5 000 symbols = ~25 GB across the cluster — the entire market fits in the memory of a few machines.
- Event log volume: ~10 TB/day. 1 M/s at peak, averaging ~100 k/s over a 6.5-hour session ≈ 2.5 B events/day × ~200 B = ~500 GB/day of orders, and several times that with fills and book deltas: ~10 TB/day in total, retained seven years in cold storage.
- Market data fan-out: ~5 GB/s. 2 000 subscribers × full depth updates at ~2.5 MB/s each = ~5 GB/s, which is why data is multicast to a fan-out tier rather than unicast from the engine.
- Matching cost per order: ~1 µs. A price level lookup in an array indexed by ticks, then a walk of a linked list at that level: a handful of cache-friendly memory accesses, ~1 µs. The remaining 99 µs of the budget is network, serialisation and sequencing.
- Replication cost: ~30 µs. Replicating each sequenced event to two standbys in the same rack before acknowledging: ~10–30 µs on a tuned network. This is the price of not losing acknowledged orders, and it is a third of the whole budget.
Components
- Participant (FIX / binary): A broker, market maker or algorithmic trading firm, usually co-located in the same building. Sends orders and cancels, consumes its private fill stream and the public market data feed.
- Order gateway: Terminates the session, authenticates, decodes the wire protocol into the internal binary format, and timestamps arrival with a hardware clock. Deliberately thin: everything it does is on the latency budget.
- Pre-trade risk: Credit, position and sanity limits, evaluated from in-memory state in a few microseconds. Nothing reaches the book without passing it, because an exchange that lets a participant trade beyond its credit becomes the counterparty to the loss.
- Sequencer: The single point that decides order. Stamps every message with a monotonic sequence number and a timestamp, and that stamp is the definition of "first". One process per symbol group; its throughput is the market's throughput.
- Sequenced log (replicated in-memory ring + disk): The ordered, durable record of every input. The matching engines are pure functions of this log, which is what makes replay, recovery and audit the same mechanism.
- Matching engine (single-threaded, in-memory book): Consumes the log in order and applies price-time priority. Single-threaded on a pinned core with no allocation in the hot path: determinism first, and the speed follows from having no locks rather than from clever parallelism.
- Order book (in-memory, per symbol): Price levels as an array indexed by ticks, each level a linked list of resting orders in arrival order, plus a hash from order id to node for O(1) cancel. Cancels are most of the traffic, so the structure is shaped around them.
- Hot standbys: Engines consuming the same log and applying the same transitions, in lockstep. Because the engine is deterministic, a standby is not a copy of state — it is the same computation, so failover is promoting a process that is already correct.
- Market data publisher (multicast): Turns engine output into book deltas and a trade tape and multicasts them, so every subscriber receives the same packet at the same moment. Unicast would make the first recipient systematically faster, which is unfair by construction.
- Subscribers: Market makers, vendors and surveillance systems. Sequence numbers on the feed let a subscriber detect a gap and request a retransmission rather than silently trading on a stale book.
- Private fill stream: Each participant's own order state and fills, delivered reliably and in order. Unlike market data, a missed message here is unacceptable, so it is replayable by sequence number per participant.
- Event archive (object store, 7 years): Every sequenced input and output, immutable, indexed by symbol and time. The regulator's copy and the input to any replay.
- Surveillance & reporting: Replays the log to detect manipulation — spoofing, layering, wash trades — and produces regulatory reports. Runs on the same log the engine consumed, so it can never disagree with what happened.
User flows
- A buy order crosses the spread. The path that defines the system. Note that ordering is decided once, early, and everything downstream is a consequence.
- A participant sends a limit buy for 500 at 101.25; the gateway decodes and timestamps it.
- Pre-trade risk checks credit, position and sanity limits from in-memory state.
- The sequencer assigns the next sequence number for the symbol group.
- The sequenced event is replicated and appended to the log before it is acted on.
- The engine reads the event and walks the ask side while the price crosses.
- Fills go to the private streams of both sides; the book delta and the trade go to market data.
- Positions update in the risk service and the event lands in the archive.
- A market maker cancels and re-quotes. Twenty times more common than a trade, and where the book's data structure earns its keep.
- The maker sends a cancel for a resting order.
- It is sequenced like any other message.
- The engine finds the order in O(1) and unlinks it from its price level.
- If the order already filled, the cancel is rejected as too late.
- A book delta is published, and the maker immediately posts a new quote.
- The opening auction, and the burst behind it. The scale-breaking case. Order rate is five times normal in the first seconds and the price is discovered by a different algorithm entirely.
- Orders accumulate during the pre-open without matching.
- An indicative price is published periodically so participants can react.
- At the bell the engine computes the single price that maximises executed volume.
- Fills are published in one burst; the book flips to continuous trading.
- Order rate peaks at five times normal for the first seconds.
- A symbol too volatile to open is held in auction rather than opened badly.
- The matching engine dies mid-sequence. The failure path. Because the engine is a pure function of the log, recovery is resumption rather than reconstruction.
- The primary engine stops responding after processing sequence 88 412 900.
- A standby that has consumed the same log to the same point is promoted.
- Fencing ensures the old primary cannot publish if it comes back.
- The new primary resumes at 88 412 901 and replays anything sequenced during the gap.
- Participants reconcile their own state from the private stream by sequence number.
- Trading resumes, typically inside a second, and the pause is published.
- Publishing the book to two thousand subscribers. Fan-out where fairness is a physical property: the same packet, at the same moment, to everyone.
- The engine emits a book delta for every change.
- The publisher multicasts the delta with a sequence number.
- A subscriber detects a gap in the sequence and requests a retransmission.
- Periodic full snapshots let a late or lost subscriber recover without a full replay.
- Surveillance consumes the archived log rather than the live feed.
Deep dives
- Deciding what happened first. How do you establish a single, provable order for messages arriving from everywhere at once? One sequencer process per symbol group, assigning a monotonic sequence number and an authoritative timestamp, replicating each event to hot standbys before acknowledging, and writing it to a durable log. Symbol groups are the horizontal axis, sized so no group approaches one core's capacity. The engine and every downstream consumer derive their ordering from the sequence number and never from a clock.
- Why the engine is single-threaded. How do you get both microsecond latency and byte-identical replay? One single-threaded engine per symbol, several pinned to dedicated cores on a machine, each a pure deterministic function from the sequenced log to fills and book deltas. No wall-clock reads, no random numbers, no iteration over unordered collections, no allocation in the hot path. Standbys run the identical binary over the identical log, and any divergence between primary and standby output is treated as a critical defect.
- The order book data structure. How do you store a book so that match, cancel and best-price are all fast? A per-side array of price levels indexed by tick offset from a rebasable origin, each level holding an intrusive doubly linked list of orders in arrival order, with a hash from order id to its node for O(1) cancel and a cached best-price index per side. Nodes come from a pre-allocated pool so the hot path never allocates, and the array is rebased during a natural pause if the price walks out of range.
- Never losing an acknowledged order. When is an order safe, and what does the acknowledgement actually promise? The sequencer replicates each sequenced event to two standbys over a low-latency fabric and acknowledges once both have it in memory — roughly 30 µs. The log is flushed to local NVMe asynchronously and shipped to the archive continuously. A remote site replicates asynchronously for disaster recovery, with an explicit and published recovery point: a site-loss failover may lose the last fraction of a second, and the market halts rather than pretending otherwise.
- Fairness as an engineering property. What does it mean for an exchange to treat participants equally, and what enforces it? Equal-length cabling to every colocated rack, identical gateway hardware and software, one sequencer deciding order, and multicast market data so every subscriber receives the same packet simultaneously. Per-gateway latency distributions are published so participants can verify there is no faster door. Where a genuine advantage remains — a participant's own hardware — it is theirs to have; what the exchange controls, it equalises.