Historical diff jobs
Use synchronous CALL patinadb.diffRange(from, to) for an interactive comparison.
It still returns rows and respects query timeouts. For a larger comparison, an
administrator can explicitly submit a node-local background job instead of
holding a request open. This does not make arbitrary Cypher asynchronous.
Submit on the private management endpoint, using your operator authentication:
POST /mgmt/diffs
Content-Type: application/json
{"database":"default","from":"<old-engram-uuid>","to":"<new-engram-uuid>","request_id":"<client-generated-uuid>"}
Use JSON null for from to compare against an empty graph. Resolve tag names
with SHOW TAGS first; endpoints are fixed Engram UUIDs, not moving names.
HTTP 202 returns job_id and state. Retrying the same request ID and options
on the same node returns the existing record; different options conflict.
| Operation | Interface |
|---|---|
| Inspect local jobs for a database | USE default SHOW JOBS (kind=diff) |
| Inspect one job | GET /mgmt/diffs/{id} |
| Retrieve a result page | GET /mgmt/diffs/{id}/rows?offset=0&limit=100 |
| Request cancellation | POST /mgmt/diffs/{id}/cancel |
| Remove a terminal job and its result | DELETE /mgmt/diffs/{id} |
Wait for ready before reading results. cancelling means work has not yet
stopped; wait for cancelled before deleting. Other states are queued,
running, failed and expired. Detailed failure diagnostics are in the node
log. A failed job is not a partial successful diff.
Pages return rows and next; pass next as the subsequent offset until it is
null. A row has change and data: change is vertices_added, vertices_removed,
vertices_moved, vertices_changed, edges_added or edges_removed. Data is the
corresponding core SnapshotDiff record; property values are typed JSON, e.g.
{"Integer":42}. This format is not the synchronous procedure’s flat row schema.
The existing comparison contract does not report secondary-label changes or
edge-property-only changes.
Operational limits
Small forward ranges of property/secondary-label updates can compare only the
affected existing vertices when the complete logged transition is provable.
Existing snapshot point indexes are reused; without an index, a baseline scan
still occurs but only selected vertices are retained. Structural mutations,
snapshot-only transitions and unsupported ranges retain full comparison.
This optimization is not the AS OF query engine and does not change its paths.
All operations require global Admin plus database authorization. Do not expose them as raw exports to application users with only label-level permissions. Jobs/results belong to the submitting node; polling another node is not failover. Queued and running jobs fail on restart rather than silently changing their source. Completed results survive restart, expire after 24 hours, and are not a backup or replicated audit record. Resubmit after losing the node.
Persisted state names remain queued, running, ready, failed, expired,
cancelled and cancelling. An unrecognized state in the local job manifest is
reported as an error; it is not silently shown as a failed job or rewritten.
The manifest and result files are retained for diagnosis.
There are at most 16 retained jobs and one executing diff per node. Delete terminal entries when the queue is full. Diff execution does not take the tag/backup execution slot, but it still competes for host resources. Active comparison protects required history from destructive retention; queued jobs do not pin history and may fail if their endpoints are pruned before admission.
The default PATINADB_DIFF_MAX_BYTES is 4294967296 bytes of cumulative allocation
accounting, not a hard RSS limit. It covers both endpoints and charges replay
work without refunding deletions. Larger graphs or long update chains may need
an operator-selected larger value and adequate host memory. This setting also
applies to synchronous structural diffs. The engine compares snapshot records
and checked deltas without constructing two temporary graph databases, but still
holds comparison maps in RAM; there is no spill-to-disk fallback.
Jobs have a one-hour execution deadline. Results plus index are capped at 1 GiB, each encoded row at 1 MiB, and artifact writes check a 1 GiB free-space reserve. Pages contain at most 100 rows / 4 MiB encoded row payload; four page readers may be admitted concurrently. Cancellation is cooperative, not an immediate kill. Resource limits and damaged/missing history produce errors, not incomplete data.
The #1294 local 1M qualification covers the unindexed bounded update path,
the structural fallback, near/distant endpoints, concurrent traffic,
cancellation and restart using an explicitly larger accounting budget, not the
default. Unindexed scans still take time; structural fallbacks still need full
comparison maps. Queueing alone is not the bounded update optimization.
See docs/history-diff-1294-2026-09-12.md in the source tree
for measured intervals, resource use and failed attempts. No production approval
follows from this single-host qualification.