An exchange looks like a simple database problem: buyers and sellers send orders, and orders that agree on a price become trades. What makes it hard is that the order of events is the product. Two firms send a buy order in the same microsecond, and only one can be first in the queue. "First" has to be decided once, fairly, in microseconds, and recorded so it can be replayed and audited years later, without ever losing an order or executing one twice.
The answer is a design that would look odd anywhere else: put every order into one sequence, then process that sequence on a single thread.
The brief
You're building the trading core of a stock exchange. Firms send orders to buy and sell shares. The exchange matches them, tells both sides what happened, and publishes every change so the whole market sees the same prices.
Who uses it?
- Member firms: brokers and market makers, connected over long-lived TCP sessions, often from servers in the exchange's own data centre. Some send thousands of orders a second and cancel almost all of them.
- Retail investors use a broker's app. Only the broker talks to the exchange.
- The clearing house receives every trade and makes sure shares and money change hands.
- Regulators expect an exact record of everything.
In scope: order entry (new, cancel, modify), pre-trade risk checks, matching, acknowledgements and fill reports, market data, failover, and handing trades to post-trade systems.
Out of scope: how clearing and settlement work inside the clearing house, payments between brokers and their customers (see the Razorpay lab), market surveillance, derivatives and margining, and the details of opening and closing auctions.
Requirements
Functional
- Members submit limit orders ("buy 300 at ₹412.50 or better") and market orders ("buy 300 at whatever the best price is"), and can cancel or modify them.
- Orders match by price-time priority: the best price first, and at the same price, whoever arrived first.
- An order can be partially filled. Whatever is left of a limit order rests on the book until it fills, is cancelled, or the day ends.
- Members get an acknowledgement for every order and a fill report for every execution.
- Everyone gets market data: every change to the book and every trade.
- Pre-trade checks reject orders that break a member's limits or are priced absurdly far from the market.
- Every trade goes to clearing after the match.
Non-functional
- Fair: the same rules for everyone. Priority depends only on when an order reached the exchange's sequencer, never on which server or thread happened to pick it up.
- Deterministic and auditable: replaying the day's input reproduces every fill exactly, to the share and the paisa.
- No lost, no duplicated orders: once acknowledged, an order survives the failure of any single machine. An order is never executed twice.
- Fast: matching takes under 50 µs (microseconds) inside the engine, and a member in the exchange's data centre gets an acknowledgement in under 1 ms.
- Available during market hours: failover in under a second, with no acknowledged order lost. Outside market hours, the system can be down for maintenance.
The last line matters. An exchange is open about six hours a day, which gives it a luxury most systems lack: a quiet night for upgrades and reconciliation. Several choices below lean on it.