The one breaking change: result frames are pyarrow.Table
DedupeResult.golden, .dupes, .unique and MatchResult.matched,
.unmatched now return pyarrow.Table (they were polars.DataFrame).
If you consumed those frames with Polars, migration is one line:
Everything else on the result objects is unchanged:
result.clusters,
result.stats, result.scored_pairs, to_csv, the notebook display, and
__repr__ all behave as before.
Inputs are NOT affected
dedupe_df / match_df accept Polars, pandas, and Arrow inputs exactly as in
v2 (Arrow C stream polymorphism). Your ingestion code does not change.
The Arrow backend is now the default
GOLDENMATCH_FRAME defaults to arrow — the measured-faster lane (~36%
faster end-to-end on the 100K zero-config A/B benchmark). Behavior is
output-equivalent to the Polars lane, enforced by a differential harness with
frozen fixtures.
If you need the old lane while validating the upgrade:
polars moved out of the
required dependencies — pip install goldenmatch runs the engine end to end
on Arrow (a zero-polars CI gate proves a full dedupe with polars imports
blocked). The polars-free install is also the FAST configuration: measured
head-to-head, the Arrow lane without polars beats the polars-present run
(the Rust fused kernels own the hot paths). The [polars] extra is a
COMPATIBILITY surface — the classic GOLDENMATCH_FRAME=polars lane, the
golden fast-columnar replay when the native kernel is absent, and
goldencheck cell-quality weighting — byte-identical to 3.0.x behavior, not
an accelerator.
Notes for specific surfaces
- MCP / A2A: tool responses were already JSON — no change.
- dbt (
dbt-goldensuite): unaffected — the internal pipeline result frames arepyarrow.Tableon both lanes since the engine descent completed. - One behavioral nuance: sampling-based auto-config decisions are
deterministic per backend but may legitimately differ between the
arrowandpolarslanes (documented statistical contract ofFrame.sample).