Dependency and change tracking
Most operational systems record that their own data changed. They do not know every business result, context, projection, cache or channel representation that depends on it. That missing knowledge is why cross-system business rules tend to become custom integration code and why supposedly incremental flows are backed by broad nightly runs.
Vox records both sides of the problem: what a derived result depends on, and what changed. It can then identify the affected work, recalculate it, and expose a settled result without scanning everything that might conceivably be related.
Dependencies come from actual reads
A calculation, assessment, membership rule, cached reference or published entity projection reads through a Vox evaluation context. Vox records the data that was actually observed during that evaluation:
- Entity properties, including properties inside nested objects.
- Existing entities and entities that do not exist yet.
- Relations, including a relation that is currently empty.
- Context memberships, including memberships that are currently absent.
- Singleton settings shared by many calculations.
- Named application dependencies, such as an exchange rate or feature configuration.
- Future instants at which a time-dependent answer may change.
Tracking absence matters. If a product has no stock record today, its availability still depends on that missing record. Creating the first stock record must therefore make the product eligible for recalculation. The same applies to adding the first relation or context membership.
Dependencies are refreshed whenever the consumer runs. If a campaign stops affecting a product, the next successful evaluation removes that relationship from the graph instead of leaving a permanent subscription to obsolete inputs.
Changes are recorded durably
Entity, relation, context-membership and named dependency changes enter a normalized change journal. With transactional authoritative storage, the changed data and the records needed to propagate its consequences commit together. A process failure after that commit can delay work, but it cannot make the committed change invisible to the dependency system.
Consumers maintain watermarks over the journal. A watermark advances only through changes whose affected work has been accounted for. Nexus jobs and queues provide durable wakeups, retries and scheduling around that state.
This is deliberately an at-least-once model. Vox does not depend on the fragile promise that a message is handled exactly once. Repeated wakeups and evaluations are safe; losing the consequences of a committed change is not.
Only affected work runs
Before queuing work, Vox matches new journal records against the stored dependency graph. Several changed inputs for one product are coalesced into one product evaluation. A burst of price, stock and campaign updates therefore does not need one calculation per input change, nor a scan of every product.
The dependency graph is shared by several kinds of consumer:
- Calculated field groups maintain derived entity data.
- Context-membership calculations determine where an entity belongs.
- Evaluated assessments maintain quality, readiness, risk or health results.
- Cached references refresh denormalized target data.
- Durable entity projections publish application-facing representations incrementally.
Each consumer keeps its own progress. A failure in one output does not make another consumer forget what it has already processed, and retrying one consumer does not require rebuilding every other output.
Settling creates a reliable handoff
A source write can commit before every consequence has been calculated. Its early entity event names the calculated groups and memberships still pending. When that work completes, Vox emits a consistent event containing the complete change since the preceding settled state.
That consistent event is the safe handoff for subscriptions and other consumers that require a settled result. Vox's
search flow processes the entity versions produced along the way through a durable outbox, and version checks prevent
stale work from replacing a newer document. Read caches are refreshed from committed authoritative data and fall back
to it on a miss or failure. Durable projection publications keep their own dependency watermarks. A channel can
therefore choose the latency and consistency boundary appropriate for its output without inventing an arbitrary
delay. Imports expose the same distinction through their processed, settled and indexed milestones.
Draft and release scopes keep their own dependencies and derived data. A preview therefore shows results calculated from its own graph without contaminating the published flow.
Time is an input too
Some results become stale without an entity write: a price expires, a campaign begins or an offer reaches its end.
During evaluation, RecalculateAt records the earliest future instant at which the answer may change. Vox schedules
that recalculation durably and replaces the schedule when a later evaluation discovers a different boundary.
Time-dependent rules therefore use the same dependency and settling model as data-dependent rules. They do not need a periodic scan to discover which records crossed a boundary.
From defensive rebuilds to trusted deltas
A full rebuild remains useful for initial population, deliberate backfills and recovery. It should not be the normal mechanism that makes an incremental flow eventually correct.
Vox makes the delta path the correctness path: dependencies say what may now be stale, the change journal ensures a committed change is remembered, watermarks make progress explicit, and consistent events identify when the result is ready for delivery. This is what lets a team trust that a change in one source reaches every affected rule and channel without recomputing the entire estate each night.
See Calculations, Events and subscriptions, Entity projections and Storage and infrastructure.