The order state machine
Every state an order can occupy, every legal transition — and why enumerating them kills a whole class of bugs.
1.2 showed one happy path; 1.3 showed partial fills. This lesson closes the map: all the paths.
Distributed-systems bugs love undefined states: "the cancel arrived while the fill was in flight — now what?" The exchange's answer is to make the order's lifecycle an explicit state machine, and to let the matching engine alone perform transitions. Everyone else — gateways, risk, the trader — merely requests transitions and learns the verdict from execution reports.
stateDiagram-v2
[*] --> Pending: received by core
Pending --> Rejected: fails validation or risk
Pending --> Filled: fully matches on arrival
Pending --> PartiallyFilled: partly matches on arrival
Pending --> Live: no match, rests on book
Live --> PartiallyFilled: incoming order matches part
Live --> Filled: incoming order matches all
Live --> Canceled: cancel request honored
Live --> Expired: time in force runs out
PartiallyFilled --> Filled: remainder matches
PartiallyFilled --> Canceled: remainder canceled
PartiallyFilled --> Expired: remainder expires
Rejected --> [*]
Filled --> [*]
Canceled --> [*]
Expired --> [*]
The diagram resolves the classic race by construction. Alice sends a cancel at the same moment Bob's order is matching hers. Both requests enter the engine's single input stream (1.3); whichever the engine processes first wins, and the state machine makes the loser's outcome well-defined:
- Cancel first → order is
Canceled; Bob's order matches elsewhere or rests. - Match first → order is
Filled; the cancel arrives to find no live order and returns too late to cancel — an ordinary, expected response, not an error.
This is worth internalizing as a method: races don't get resolved by cleverness at the edges; they get resolved by total ordering at the core, plus a state machine with no undefined cells.
- Orders live in an explicit state machine with absorbing terminal states.
- Exactly one writer — the engine — performs transitions; all else requests.
- "Too late to cancel" is a normal answer, designed in, not an error bolted on.