Design a stock exchange

Ten thousand symbols, a million orders a second at the open, a match in under a hundred microseconds, and no order ever lost. The round turns on one sentence: one sequencer numbers every order into a log, and one single-threaded engine per symbol replays that log into the book.

The round this design follows

Why is the matching engine single-threaded?

Because price-time priority is one total order per symbol: the best price fills first, and at one price the oldest order fills first. Two threads matching one book would need a lock on every order to agree on that order, and the lock costs more than the match. One thread per book, working through orders in sequence, matches an order in about 2 µs, which is 500 thousand orders a second on one core. Parallelism comes from giving different symbols to different engines, never from splitting one book.

What does the sequencer do, and is it a single point of failure?

It gives every order a number and appends it to a log before any engine sees it. That number is the one order of events the whole exchange agrees on, so the engines, their standbys and the market data all follow it. It is a single point by design, so it runs with a hot standby that holds every entry before the order goes on, and a failover after three missed 1 ms heartbeats. At 0.5 µs an order it does 2 million a second, twice the open, and it is the first box to split when the prompt grows tenfold.

What happens when a matching engine crashes?

Its hot standby has been reading the same sequenced log and applying every order to its own copy of the books, so it holds the same state. It notices the primary is gone after three missed heartbeats, 3 ms, and carries on from the next sequence number; the orders numbered meanwhile wait in the log and are applied in order. Nothing that was sequenced is lost, because the log was written before the engine saw it. A cold engine would replay the day instead, about 7.8 minutes late in a session.

Why not keep the order book in a database?

A database with row locks does about a thousand orders a second on one symbol, because every order on that symbol locks the rows at its best price and waits for a synced commit of about a millisecond. A symbol on breaking news can take 450 thousand a second, 450 times that. The exchange keeps the book in memory and makes the sequenced log the durable record, so durability costs one append per order, not a transaction.

How do you send market data to 100 thousand subscribers?

Not one copy each: the full feed is 64 MB/s, and a copy to each subscriber would be 6.4 TB/s. The publisher sends each event once, by multicast, to a small relay tier and to members who take the full feed. Relays send each subscriber only the symbols it follows, conflated to the latest state ten times a second, which is 3.2 GB/s in all and three relays. A subscriber that falls behind gets the latest state, never a growing backlog.