Install the CLI, write your first suite, and locate a real difference in under ten minutes
On this page, you run a reconciliation on your own machine. You see it report a mismatch, and you narrow the mismatch down to the two rows that cause it.The walkthrough uses a self-contained dataset, so you need no warehouse and no credentials. At the end, a small change points it at your own databases.
To update, run brew upgrade synq-recon. Homebrew is for macOS only. See
Command-line tools for the other ways to install.
Every published binary runs DuckDB, which is what the walkthrough below uses so
it needs no warehouse and no credentials.
The archive file name contains the version, so you must name it. The first
line reads the version from the
releases page:
VERSION=$(curl -fsSLI -o /dev/null -w '%{url_effective}' \ https://github.com/getsynq/synq-recon/releases/latest | sed 's#.*/v##')OS=$(uname -s | tr '[:upper:]' '[:lower:]') # darwin or linuxARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')curl -fL "https://github.com/getsynq/synq-recon/releases/download/v${VERSION}/synq-recon_${VERSION}_${OS}_${ARCH}.tar.gz" \ | tar -xzsudo mv synq-recon /usr/local/bin/
Builds are published for macOS and Linux on both amd64 and arm64, and for
Windows on amd64 (see the Windows tab). Each archive
also carries the operating guide and the example suites, and every release ships
a checksums.txt you can verify with
sha256sum -c checksums.txt --ignore-missing.
Every published binary runs DuckDB, which is what the walkthrough below uses so
it needs no warehouse and no credentials.
On macOS a downloaded binary may be quarantined. If it refuses to start,
xattr -d com.apple.quarantine /usr/local/bin/synq-recon clears the flag.
Download synq-recon_<version>_windows_amd64.zip from the
releases page, then in
PowerShell:
Expand-Archive synq-recon_<version>_windows_amd64.zip -DestinationPath "$env:LOCALAPPDATA\synq-recon"$env:Path += ";$env:LOCALAPPDATA\synq-recon" # this session; add it to your user PATH to keep itsynq-recon --version
The Windows build runs DuckDB too, so the walkthrough’s suites run there. Its
synq-recon commands work as written in PowerShell, except the last one, which
is a bash pipeline into jq.
Get-FileHash -Algorithm SHA256 <archive> gives the value to compare against
the release’s checksums.txt.
The image runs DuckDB. The walkthrough below uses DuckDB, so it needs no warehouse. If a type: duckdb connection fails with a driver error, your image is older than DuckDB support. Pull :latest.
A suite is a YAML file that holds the connections and the reconciliations. Save this as quickstart.yaml:
quickstart.yaml
# yaml-language-server: $schema=https://schemas.synq.io/synq-recon/v1/config.schema.jsonname: quickstarttitle: Quickstartconnections: local: duckdb: database: ":memory:"# Stands in for two real systems: an application database and the warehouse# copy of it. The copy is missing one order and has the wrong amount on another.setup: local: - | CREATE TABLE app_orders AS SELECT i AS order_id, 'CUST-' || (i % 7) AS customer_id, i * 10.0 AS amount FROM generate_series(1, 1000) AS t(i) - | CREATE TABLE warehouse_orders AS SELECT order_id, customer_id, CASE WHEN order_id = 617 THEN amount + 5 ELSE amount END AS amount FROM app_orders WHERE order_id <> 384reconciliations: orders: title: Orders (application vs warehouse) source: connection: local table: app_orders target: connection: local table: warehouse_orders key_columns: [order_id] mode: row_checksum bisection: factor: 10 threshold: 10
That first line points your editor at the published JSON schema, which gives you completion and inline validation for every field. Keep it at the top of every suite you write.
The bisection block is tuned small here so the drill-down has something to do on a thousand rows. On real tables the defaults are the right starting point.
Checking configuration: quickstart.yamlConfiguration Summary=====================Connections (1): - local (duckdb)Reconciliations (1): - orders Source: local Target: local Key Column(s): order_id Mode: row_checksum Bisection: factor=10, threshold=10Configuration check passed!
This costs nothing and touches no database. Add --db to also connect, run every query through the database’s planner, and report table sizes, indexes and a suggested key column:
synq-recon check-config quickstart.yaml --db
--db does not run the setup: SQL of the suite, so for this walkthrough it reports that app_orders does not exist. This is expected. The setup SQL makes the tables when the reconciliation runs.
Coalesce Quality Reconciliation - Quick Check============================================Reconciliation: Orders (application vs warehouse) (orders)Mode: row_checksumDuration: 6ms Source TargetRow Count 1,000 999Status: MISMATCH - Source has 1 more rows than targetHint: Run 'synq-recon run-drill <config> --include orders' to locate differences.
Two queries, one per side, tell you that the datasets do not agree. If they agreed, this would be the full run.
The command exits 1. For a comparison, a non-zero exit means “differences found”, which is a result rather than a failure. Exit codes has the full list.
--no-report keeps the run entirely local. Without it, a run reports its results to your workspace whenever it can find a credential, so they show up in the app alongside backend runs.
Read that from the top. The whole dataset disagrees, so it is split into ten segments; eight of them match on the first comparison and are never looked at again. The two that differ get split again, and the run stops with two ten-row windows to inspect.Look at the shape of each finding. The segment around order 384 has one row less on the target: a row is missing. The segment around order 617 has the same count but a different checksum: a value changed. You did not read a row value yet.
The drill-down compared 33 segments with 17 queries, and found two bad rows in a thousand. The saving grows with the table, because the number of queries grows with the logarithm of the row count, not with the row count. This is the purpose of the drill-down.
Run these queries on the two databases to see the rows. This is the first time that row values are read: by you, in your SQL client, for ten rows and not for a million.
Redirect logs with 2>/dev/null, never 2>&1. Logs go to stderr and results to stdout; merging them makes -o json unparseable.
Then run the same four commands. Two things to do before you trust the result:
Keep the credentials out of the file. Move the connections: block to a git-ignored .connections.yaml. The CLI finds it automatically. See keep credentials out of the suite.
Run check-config --db. It checks every connection and query, and warns if your key column has no index. Without an index, a drill-down can take minutes and not seconds.