After a restart, every open order must still have the right quantity and priority. Completed trades must remain completed. Retried requests must not create a second trade. Account, position and market-data services need a way to catch up with what the engine committed.
Those requirements account for much of the work in an exchange. Latency and throughput matter, and writing correct matching logic demands care. Running that logic reliably also means keeping orders, trades and their history consistent through load, failures and upgrades.
The work around matching
At the center, an order handler decides whether to accept an order, how it matches available liquidity, which fills it produces and how much quantity remains open. Depending on the system, that decision also affects balances, positions and risk checks.
Around the handler, the platform must establish command order, record decisions durably, recover state and deliver events to other services.
The difficult cases often occur where these responsibilities meet: a connection drops after a command commits, a process stops during a snapshot, or an event consumer falls behind.
A retry must not become another trade
Commands arrive from gateways, internal services and operator tools. Connections fail, clients retry and requests can arrive more than once. The system needs to distinguish receiving a command from committing and applying it.
A client that loses its connection needs to know which requests it can safely retry. If a leader fails, the replacement must establish whether a pending command committed. A later duplicate must be recognized by its identity, even after a reconnect or restart.
Keeping the relationship between client request identities and the engine's transaction sequence makes those questions answerable. Losing that relationship leaves both clients and operators unsure whether an order was processed.
Recovery must reproduce committed state
Recovery must reconstruct the open orders, completed fills, balances and positions established by committed commands. It also needs a precise point from which to resume processing. Event consumers have a separate responsibility to track which outputs they have already delivered.
The recovery process needs:
- a durable history of committed commands;
- a snapshot tied to a known position in that history;
- replay of the committed commands after the snapshot;
- checks that the reconstructed state matches the expected result;
- retry handling that continues to recognize stale or duplicate requests.
A process can start successfully while holding the wrong state. That makes verification part of recovery itself: a healthy process is only useful if it resumes the correct business history.
Snapshots need a precise place in history
A busy engine continues to process commands while a snapshot is being written. The snapshot must still represent a consistent state at a known transaction position.
The design has to account for the practical details. How long does snapshotting pause execution? What happens if a disk write fails halfway through? How is a completed snapshot checked before it becomes eligible for recovery? Which committed commands must be replayed after it?
An incomplete or inconsistent snapshot can restore the wrong state even when the remaining log is intact. Snapshot creation, validation and selection therefore belong to the same recovery design as the command history.
Failover must preserve committed work
Deterministic execution within one process is a useful starting point. Failover adds the responsibility of continuing that execution safely on another node.
A replacement leader must follow the cluster's election and membership rules and have the state required to continue committed work. The system must prevent competing leaders from making independent decisions, and prevent a node that is missing committed commands from serving as if it were current.
External publishers also need clear ownership and delivery progress so that a leader change does not leave them guessing which outputs to send again.
Health checks help detect failure. Correct failover also depends on command history, recovered state and authority to continue processing.
Events must follow committed decisions
A matching engine feeds many other systems:
- order-book and candlestick market-data views;
- database tables used for queries and reporting;
- account, position and open-order services;
- risk services and WebSocket updates;
- reconciliation, audit and operational monitoring.
Publishing an event before its state change is durable lets consumers act on a decision that may disappear after a crash. Duplicate events require idempotent consumers. Missing or reordered events can leave market data, account state and risk views out of agreement.
Event delivery needs to follow the same committed history that determines the engine's state, with consumers tracking their own progress through it.
Read models need a shared reference point
Each consumer arranges data for its own task. Market-data services maintain order books and candlestick charts. Account services answer balance and position queries. Risk services track exposure, while WebSocket services deliver timely updates.
These views can advance at different rates. A recorded transaction position lets an operator distinguish a delayed view from one that has processed the same history incorrectly.
Without that reference point, even a simple disagreement becomes difficult to diagnose:
The engine's committed history provides the reference. Consumers can identify what they have processed, what they have missed and what they need to replay.
Upgrades must account for existing history
An upgrade changes more than a running executable. The new version may need to read existing records and snapshots, interpret earlier commands and remain compatible with event consumers.
If a handler changes, replay needs a defined rule for which version of the business logic applies to each part of history. Schema changes need a migration plan. Event changes need compatibility rules. A failed upgrade needs a recovery or rollback procedure that preserves committed work.
These requirements are easier to address when state, command history and execution versions are explicit. Leaving them to manual repair makes each upgrade harder to reason about.
Why StateVec uses deterministic execution
StateVec combines deterministic business logic with a replicated command history. In Verify mode, the leader simulates commands and followers repeat the execution and compare results before acknowledging replication. Consensus establishes which commands commit; each node then applies them in order and checks its local result.
Recovery starts from a selected checkpoint and replays the committed portion of the log after it. Event delivery and audit integrations consume that history while maintaining their own progress.
This gives the surrounding systems a common basis for recovery and diagnosis. Multiple nodes can rebuild the same state and compare execution results. Read models can trace their data back to committed transactions. Business developers can focus on matching and risk rules while the engine handles the shared execution and recovery work.
For the details, read how StateVec handles replication, execution verification and recovery.