Two statuses, and they mean different things
A
succeeded run reporting mismatched is the normal, healthy case — the tool did its job and found something. Filter on the result status, not the run status, when you want “did anything differ?”.Reading a finished run
- CLI
- App
The segment tree
Inrow_count and row_checksum modes, a drill-down produces a tree of key ranges. Each node carries both sides’ count and checksum, and the leaves are where drilling stopped:
20/1,000 rows in mismatched segments is the useful number at each level: it is how much of the dataset is still in play. If it stays close to the total as you descend, the data is not mostly-identical and you are in the expensive case.
The app renders the same tree graphically, plus a drift map — the key space with the divergent regions highlighted, which makes “the whole tail is wrong” versus “three rows scattered” obvious at a glance.
What a mismatch leaf tells you
Read the types, not the counts. Every type that applies is reported, so a segment that differs in both size and content reports two:
Each leaf also carries a
drill_stop_reason, which tells you whether the finding is as narrow as it can get:
The aggregate drill tree
Inaggregate mode the equivalent output is a hierarchy of groups, each labelled with why it diverged — MEASURE_MISMATCH for its own numbers, SUBGROUP_MISMATCH for something below it. Comparison modes has a worked example.
Follow a finding to the rows
Every mismatch leaf comes with investigation queries: ready-to-run SQL for both sides, scoped to that leaf’s key range.- CLI
- App
Re-check and Drill deeper
Two operations on a finished run, rather than on a suite. Both take either a local audit-log file or, for a run stored in the workspace, its invocation id.- CLI
- App
--threshold 2:
Four things that govern a replay
Queries are replayed, not re-derived
Queries are replayed, not re-derived
The audit log holds each query after variable interpolation and cutoff resolution, so a re-check compares the same window as the original run. That is precisely what makes “did the gap move?” a meaningful question rather than two unrelated measurements.The consequence: a replay does not pick up an edited query, a changed variable, or a new cutoff until you pass
--reresolve. And --reresolve is required for an as_of reconciliation, which otherwise re-compares the same frozen snapshot forever and can never turn green.Only what was left open resumes
Only what was left open resumes
drill-deeper picks up the segments the previous run stopped at on its threshold or depth limit. --depth counts from the depth they already reached, so it means “this many more levels”.Segments that could not be split further, and aggregate groups present on only one side, are reported and skipped rather than silently dropped. An aggregate drill already visits every configured group column, so resuming one needs at least one --add-group-column.recheck re-runs only what did not pass
recheck re-runs only what did not pass
By default.
--all re-runs every reconciliation in the run.Credentials never come from an audit log
Credentials never come from an audit log
It records connection names only, never credentials. Pass
--connections, exactly as for a normal run — no connections available to replay run ... is what a missing one looks like.--remote hands the replay to our backend, against workspace integrations instead of local credentials. It needs a stored run’s invocation id — a local file has nothing server-side to reference — and accepts --include but not --exclude.
Reading an audit log directly
The audit log is the machine-readable form of everything above, and its shape is published:Audit log reference
Every field, rendered.
audit-log.schema.json
Validate a log against the schema you were sent.
jq starting points, and the two traps worth internalising: snake_case in a local file versus camelCase from the API, and counts encoded as strings.
Next
Time windows and cutoffs
Before you chase a difference, rule out the comparison window.
CI/CD and automation
Turning a reconciliation into a gate that blocks a bad release.