In-memory sequencer
A sequencer puts all orders for one market in a single line, and one thread matches them in memory. One matching core handles 1,000,000 orders/s at a 0.01 ms median. A database commit for each order cannot keep up with 300,000 orders/s.
See it on the board
The same traffic runs on two boards. The simulator measured both when this page was built.
| Measure | Goal | Each order waits for a database write | One thread matches in memory |
|---|---|---|---|
| p99 latency | under 1 ms | 2.3 s Fail | 0.3 ms Pass |
| Error rate | under 0.01% | 98.3% Fail | 0% Pass |
| Monthly cost | 32 USD/mo | 45 USD/mo |
Key numbers
| Number | Value |
|---|---|
| Orders per second, one matching core | 1,000,000 orders/s |
| Match time, median | 0.01 ms |
| Hop between two parts on one host | 0.05 ms |
| Database writes per second, one vCPU | 2,500 writes/s |
Calls per page: 20 · 18% of pages wait 2.0 s
How it works
A trading engine must give every order one place in time. If two threads match the same market, they must agree on who was first, and agreement costs time. A sequencer avoids this: all orders for a market enter one line, and one thread matches them in order. The result then does not depend on timing.
The book lives in memory. A match is a few operations on memory, so one core handles 1,000,000 orders/s. The gateway sits on the same host, and a hop costs 0.05 ms and not the 12 ms of a hop across services.
The naive design writes each order to a database before it matches. The mini board sends 300,000 orders/s. One vCPU of Postgres takes about 2,500 writes/s, so the journal would need 120 database vCPUs, and p99 stays far above the 1 ms limit.
The order log still matters. In a real system the sequencer streams its input to a standby, which replays the same orders and reaches the same state. That copy runs beside the order path, not in it.
One thread is also one limit. When one engine is not enough, split the instruments over several engines.
In the levels you remove the slow hop from the order path.