> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bensevern.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating to v3

> GoldenMatch 3.0.0: Arrow-native results and the Arrow frame backend by default

GoldenMatch 3.0.0 completes the public half of the Polars-eviction program:
results are Arrow-native, and the Arrow frame backend is the default engine
lane. Inputs are unchanged.

## 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:

```python theme={null}
import polars as pl

result = gm.dedupe_df(df)
golden = pl.from_arrow(result.golden)   # zero-copy back to a Polars frame
```

Common direct translations if you'd rather stay on Arrow:

| v2 (`pl.DataFrame`)      | v3 (`pa.Table`)                       |
| ------------------------ | ------------------------------------- |
| `frame.height`           | `table.num_rows`                      |
| `frame.columns`          | `table.column_names`                  |
| `frame.to_dicts()`       | `table.to_pylist()`                   |
| `frame["col"].to_list()` | `table["col"].to_pylist()`            |
| `frame.write_csv(path)`  | `result.to_csv(path)` (works on both) |

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:

```bash theme={null}
pip install 'goldenmatch[polars]'   # v3.1.0+: polars is an optional extra
export GOLDENMATCH_FRAME=polars     # opt-out escape hatch
```

**v3.1.0 resolution**: the Arrow descent completed. `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 are `pyarrow.Table` on 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 `arrow`
  and `polars` lanes (documented statistical contract of `Frame.sample`).
