Many backend services follow a familiar path. They receive a command, decode it into a request type, load domain objects, run business rules, save the changes and emit events. Database tables support queries and reporting. Checkpoints and recovery tools are added as the service grows.
This is a productive way to build software. Each layer solves a useful problem, and teams can evolve those layers independently. The harder question comes later: can the service reconstruct exactly how it reached its current state?
A useful starting point
A service with an in-memory business model often looks like this:
Protobuf defines the messages exchanged between services. Compatibility rules let those messages evolve as fields are added and services are upgraded. Domain objects give developers a vocabulary for the business: orders, positions, limits, balances, accounts and fills.
Databases provide persistence, indexes, queries, migrations and backups. When a service keeps its working state in memory, database tables often hold projections: representations of that state arranged for reporting, reconciliation or operational queries. Checkpoints preserve a state from which the engine can recover.
Events tell other systems what happened. Risk services, reporting tools and analytics can consume those events without becoming part of the command handler.
These separate representations give teams room to work. An API can evolve under its compatibility rules, a query schema can be optimized for a new workload, and an event can gain a new consumer. With careful transaction handling, retry logic and operational procedures, this architecture supports substantial production workloads.
Recovery exposes the gaps
Replay, audit and incident response require more than a view of the latest records. They require an explanation of how those records came to exist:
- Which command caused the change, and what state did it read?
- Did the business rules accept the command, reject it, or fail to complete?
- Which records changed, and which events were produced?
- Were the changes durable before the events were published?
- Can the same commands be replayed to produce the same result?
The information needed to answer those questions may be scattered across several systems.
A database row shows what was stored. An event describes what a consumer was told. A log records whatever the application chose to write. Each is useful, but none necessarily describes the complete transaction.
As business rules grow more complex and state lives through more upgrades, connecting those pieces becomes a larger part of the engineering work.
Conversion code can change meaning
The code between representations deserves as much attention as the command handler. A missing request field may receive a default. An external enum may map to an internal value. A migration may populate a new column. A checkpoint loader may rebuild objects, and an event builder may expose only some of the changes.
Those choices affect how state is stored, restored and understood. They can also affect whether an old command still produces the same result after an upgrade.
This makes audit and replay difficult to add later. The service may retain the final database row, the emitted event and application logs without retaining enough context to connect them. A useful account of the transaction needs to include:
| Information | What it explains |
|---|---|
| Command and request identity | What was requested, and whether it has been seen before |
| Starting state version | Which state the command ran against |
| Outcome | Whether the business rules accepted or rejected it |
| State changes | Which records were created, updated or deleted |
| Events | Which business changes were reported |
| Position in the applied history | Where the transaction belongs in the sequence |
These details connect the request, the business decision and the stored result. They give recovery and audit something more precise to work with than a collection of side effects.
Give the transaction a clear home
The design behind StateVec keeps business concepts in the application and gives the engine explicit responsibility for state and execution.
A hedging engine still works with positions, risk settings and orders. A ledger still works with accounts, transfers, holds and balances. A matching engine still works with instruments, price levels, priority and fills.
The engine provides the common foundation:
- schema-defined records as the authoritative business state;
- controlled access to those records within a transaction;
- deterministic command execution;
- explicit outcomes, record changes and events;
- a committed command history for recovery;
- execution evidence for checking replayed results.
APIs, database views and event consumers keep their own roles. The critical state change has a defined transaction boundary, so its outcome can be understood without reconstructing it from several unrelated systems.
That is the reason to introduce a transaction core: to make the business operation itself easier to execute, recover and explain.