Skip to main content
Got ~10k lines of hand-rolled entity-resolution SQL spread across dozens of dbt models? Almost all of it encodes a small set of real decisions — a few blocking keys, a handful of comparison fields and thresholds, some survivorship rules — buried in sprawl. GoldenMatch’s dbt converter ingests your dbt project and distills it into one reusable config, then measures how faithfully that config reproduces your pipeline’s existing output. The value is distillation + proof, not faithful SQL translation. Lossy extraction is fine because it is verified — exactly the posture the Splink converter ships with.
This complements the GoldenMatch-in-dbt package: that adds GoldenMatch to a dbt pipeline going forward; this converter is for replacing hand-rolled ER a team already has. The emitted config drops straight into a {{ goldenmatch_dedupe(...) }} model.

The key enabler: the manifest, not raw SQL

The converter reads your dbt manifest.json — the structured metadata dbt compile (or dbt parse / dbt docs generate) produces — not blind .sql files. The manifest carries every model’s compiled SQL, the full ref()/source() DAG, columns, tests, and the warehouse adapter. That structure is what makes distillation tractable, and it needs no warehouse credentials (only the optional verify against a live output table does).

One command

It:
  1. identifies the models that do entity resolution (DAG + naming + shape signals);
  2. extracts the recognizable ER idioms into ONE GoldenMatch config;
  3. prints a coverage scorecard + a couldn't extract list for human review.
Add --verify <output.parquet> --source <rows.parquet> to prove it reproduces your existing clusters (below). Useful flags: --min-confidence tunes how aggressively models are identified as ER; --strict fails on any lossy finding.

Or one line of Python

conv.er_models is the ranked list of identified ER models (each with a confidence + the signals that fired), and conv.signals is every recognized signal — including the couldnt_extract items — so you can audit exactly what carried over.

Two honest value stories

The report tells you which applies, so it never over-claims an F1 win:
  • Fuzzy / probabilistic ER sprawl → an accuracy + consolidation story: GoldenMatch does the fuzzy matching the SQL did badly, in a tested engine.
  • Exact keep-latest dedup sprinkled everywhere (the common case) → a consolidation + maintainability story: 10k lines become a 20-line tested config. The “accuracy” number here is trivially ~1.0 — the win is consolidation, and conv.coverage.story says so (exact-dedup, not fuzzy-er).

What it recognizes

Over each identified ER model’s compiled SQL (dialect-aware — DuckDB, Snowflake, BigQuery in the MVP; others fall through to a dialect-agnostic core and are flagged): Everything else — arbitrary business logic, CASE ladders, priority hierarchies — is attached to the report as a couldn't extract finding with the model name + SQL excerpt, never silently dropped.

Verify it reproduces your pipeline (the trust step)

Your hand-rolled dbt ER model already produces an output table — a surrogate-key→member mapping or a canonical/golden table. That existing output is label-free ground truth. verify_against_dbt runs the converted config on a sample of the source rows and reports pairwise cluster agreement against it:
The output_table is a two-column id, cluster_id frame (name the columns with output_id_column / output_cluster_column if they differ). Verification is best-effort: a missing, empty, or non-overlapping output degrades to a skip notice, never a crash — the config is still written, it’s just a suggestion until you point it at an output table.

Boundaries (stated honestly in the report)

  • Extraction is heuristic → partial coverage. The couldn't extract list is a first-class output for human review, not a footnote.
  • Survivorship & conditional business rules are the hardest to extract. The MVP recognizes most-recent (DESC window order-by) and reports it with the exact remediation (GoldenMatch applies most_recent per field); priority hierarchies and CASE ladders are flagged.
  • Dialect variance — the MVP covers DuckDB / Snowflake / BigQuery; the long tail is flagged.
  • Verify needs the output table. With it the proof is strong; without it the config is a reviewed suggestion.