At the center of every stock exchange is one component that is smaller and stranger than people expect: the matching engine. Its whole job is to hold a book of buy and sell orders and pair them off according to a strict rule. Get that rule and its data structure right and everything else, the gateways, the market data feeds, the risk checks, is plumbing around it.
The core problem
Buyers post bids (the price they will pay) and sellers post asks (the price they will accept). A trade happens when a bid meets an ask at a compatible price. The engine has to decide, when a new order arrives, whether it crosses with an existing one, and if several resting orders qualify, which one gets filled first. That tiebreak rule has to be fair, deterministic, and fast, because on a busy day the engine sees enormous message volume and every participant expects the same rules.
Price-time priority
The standard rule is price-time priority. Better prices go first: the highest bid and the lowest ask sit at the front of the queue because they are the most competitive. Among orders at the same price, the one that arrived earlier goes first. This is the fairness guarantee that makes an exchange trustworthy. You cannot jump the queue by being bigger or louder, only by offering a better price or getting there sooner.
The order book data structure
The order book is two sorted structures, one for bids and one for asks. Each distinct price level holds a FIFO queue of orders at that price. When a market buy order arrives, you look at the best ask (the lowest sell price), fill against the orders in its queue in arrival order, and if the incoming order is larger than the resting quantity, move to the next price level and keep going until the order is filled or the book runs dry.
The operations you need are: find the best price on each side instantly, add an order at a given price level, remove or reduce an order when it fills or cancels. A common implementation is a map from price to a linked list of orders, with the best prices tracked so the top of book is O(1). Cancellations are frequent, often the majority of messages, so you also keep a direct index from order ID to its node in the book to cancel in constant time without scanning.
Why single-threaded is faster
Here is the counterintuitive part. You might reach for locks and multiple threads to go fast. The best matching engines do the opposite: they run the core matching loop on a single thread. Concurrency on a shared order book means locking, and lock contention plus cache-line bouncing between cores costs more than it saves. A single thread processing a stream of orders from an in-memory queue has no locks, perfect cache locality, and, just as important, deterministic behavior. The same sequence of orders always produces the same fills, which is essential for auditing and for rebuilding state after a crash.
The trade-off is that one thread caps your throughput at what a single core can do. Exchanges accept this because determinism and latency matter more than raw parallelism, and they scale out by running separate engines per symbol or per group of symbols. Each engine is independent, so different stocks match in parallel across cores while any single stock stays serial and fair.
Durability without losing speed
The engine holds the book in memory for speed, but a crash cannot lose trades. The standard answer is an append-only log. Every incoming order is written to a durable sequenced log before it is matched. If the engine dies, you replay the log to rebuild the exact book state. Because matching is deterministic, replay reproduces the identical set of fills. This event-sourced design gives you both microsecond matching and full recoverability.
How the real systems do it
The LMAX exchange popularized this approach and open-sourced the Disruptor, a lock-free ring buffer that feeds a single-threaded business logic core millions of messages per second. Nasdaq and other major venues run per-symbol engines with append-only journaling for recovery. The pattern is remarkably consistent: an in-memory order book, price-time priority, one thread per matching unit, and a durable log underneath it all.
I wrote the full breakdown, with diagrams and the data model, here: https://www.systemdesign.academy/interview/design-stock-exchange
Top comments (0)