When people hear "view", they often think about read models, UI tables, or database projections.
That is not the view I mean here.
In a deterministic engine, the important view is the transaction-time state surface that domain logic reads while execution is still in progress.
Speculative execution creates the need for this view. The engine has not committed anything yet, but domain logic still needs a precise answer to a simple question:
What state am I executing against?
That answer is the stacked data view.
The layers
The simplest shape has two layers:
top layer:
staged writes in the current execution context
bottom layer:
committed canonical stateReads check the staged layer first. If the record is not there, the read falls through to committed state.
Writes update the staged layer and produce deltas. The committed store does not need to change until the runtime accepts the result.
read(record):
staged version if present
otherwise committed version
write(record):
update staged layer
append state deltaThis is easy to describe for direct record access. It becomes more interesting when the engine also owns business uniqueness and ordered access paths.
UK lookup must be transaction-visible
Business engines usually need uniqueness rules. A UK is a business uniqueness key: an external or domain-level identifier that should point to one record.
Examples:
account_id
client_order_idThe UK lookup has to see staged mutations:
committed UK map
+
staged UK inserts / updates / deletes
=
UK view for current executionIf a command creates an order with client_order_id = C123, then another lookup in the same execution context should see that key. If execution rejects, that staged key disappears. If execution commits, it becomes durable.
The reverse is also important. If execution stages a delete or status change, later logic should not keep seeing a stale committed mapping as if nothing happened.
Index scan must be transaction-visible
A UK answers exact identity questions.
Indexes answer ordered access questions:
open orders by account
orders by instrument + side + price
positions by risk group
settlements by status + due date
inventory reservations by SKU + warehouseFor these paths, the stacked data view has to merge committed index state with staged index mutations.
That means an index scan is not only:
read committed indexIt is:
read committed index
merge staged inserts
remove staged deletes
apply staged key changes
return deterministic ordered resultWithout that merge, business logic can make decisions from an index view that is already wrong inside the current execution.
Prefix indexes
The useful access pattern is often prefix-based.
An index may be defined over a composite key:
account_id + status + created_seqDomain logic may need several views over that same key shape:
list(account_id)
list(account_id, status)
range(account_id, status, created_seq_from..created_seq_to)This is not a read-side projection. It is a transaction-time access path. It must be deterministic, schema-defined, and visible during execution.
For an exchange-style test case, this matters a lot. An order book is not just a display. Ordered traversal can be part of the business decision:
instrument + side + price + priority + order_idIf the execution view loses ordering, recovery and replay can produce a system that looks similar but behaves differently.
Why this differs from projections
Read-side projections are allowed to lag.
A dashboard can be a few milliseconds behind. A reporting table can be rebuilt. A search index can catch up from events.
Transaction-time views do not have that freedom.
If domain logic asks:
does this client_order_id already exist?
what is the best open sell order for this instrument?
how much position is currently available under this risk group?
which reservation should expire next?the answer has to include the staged effects that are already part of the current execution context.
That is why UK and index views belong inside the engine boundary, not only in downstream projections.
What the runtime owns
The runtime owns the mechanics:
- staged record versions;
- staged UK mutations;
- staged index mutations;
- deterministic merge order;
- rollback of rejected candidates;
- delta construction for accepted candidates.
Domain code should not hand-maintain these structures. It should express business rules through typed accessors and let the runtime maintain the transaction-visible view.
That is the difference between "I wrote a cache that happens to work" and "the engine gives me the state view this command is allowed to reason from."
Batch is a later extension
The same idea extends naturally to batch and pipeline execution.
If command N stages a mutation, command N+1 may need to see it before the batch commits. But batch is not the starting point of the design. The starting point is simpler:
one command
one transaction-visible view
one TxResult candidate
one durable boundaryOnce that contract is correct, batching is an execution strategy, not a semantic patch.
Closing thought
Stacked data view is the read/write surface of speculative execution.
It has to cover records, UK lookup, and index scans with the same deterministic semantics.
That is what lets domain logic build a TxResult before commit without guessing, leaking partial state, or depending on stale projections.
For deterministic OLTP systems, the engine has to know exactly what state a command saw before it can make the result durable truth.