mode:, and it decides what “agree” means.
Row count mode
COUNT(*) per side. Use it when the target is known to transform values — so a checksum would never match — but must not lose or duplicate rows. A drill-down still works, narrowing which key ranges have the wrong count.
Row checksum mode
columns: and exclude_columns: are how you keep pipeline bookkeeping — load timestamps, batch ids, surrogate keys generated per side — from being reported as a difference for the rest of time.
full is an accepted legacy spelling of row_checksum. Suites round-tripped through synq-recon suite yaml come back written as row_checksum.Aggregate mode
Row-level comparison is the wrong instrument when the target is a summary of the source, when row identity differs between the two systems, or when you care about the numbers rather than the rows. Aggregate mode compares measures, grouped, with a tolerance.Measures
A measure is a column and one or more functions.function: takes a single value or a list, so the block above expands to two measures: SUM(amount) and COUNT(amount). Available functions are SUM, COUNT, AVG, MIN and MAX.
The group hierarchy
group_columns: is a hierarchy, evaluated outermost-first. The comparison groups by the first column; only groups that diverge are then broken down by the second, and so on. Groups that agree are never queried again.
With group_columns: [sale_date, store_id], a run over a discrepancy on one store on one day looks like this:
STORE-1’s numbers that are wrong. Two levels, and the finding is specific enough to act on.
Each measure appears as _measure_<function>_<column> — the alias the generated SQL gives it, which is also what you will find in -o json and in the audit log. Each divergent node is labelled with why it is there:
If you omit
group_columns, the hierarchy falls back to [key_column].
Thresholds
Floating-point arithmetic, rounding, and currency conversion all produce differences that are not errors. A threshold is what separates them from the ones that are.absolute: 0 means exact agreement.
Overrides get more specific from there — per grouping column, and per measure:
1
per_column[column].per_measure[measure]
The threshold for this measure at this level of the hierarchy.
2
per_measure[measure]
The threshold for this measure, at every level.
3
per_column[column]
The threshold for every measure at this level.
4
thresholds
The suite-wide default.
"FUNC(column)" — "SUM(revenue)", "COUNT(amount)" — and the quotes are needed because of the parentheses.
A run whose only divergences are inside their thresholds reports
within_threshold rather than mismatched. That is a distinct status you can act on separately — see --fail-on.Hash algorithms
row_checksum needs a hash function that both databases compute identically. The tool negotiates the best one available on both sides, so you normally do not think about it:
Set
hash_algorithm: explicitly (auto, md5, farm_fingerprint, xxhash64) only when you have a reason to pin it — for example, to keep checksums stable across a platform migration.
Next
How comparison works
The checksum formula, bisection, segmentation strategies and privacy levels.
Time windows and cutoffs
Aggregate mode on a lagging target needs a cutoff. Here is why.
Investigating results
Reading a drill tree, and following a finding to the rows.
Configuration reference
Every field of
aggregate: and thresholds:, generated.