## TL;DR
Usage systems and CRMs mint their own ids, and the mapping between them rots through mergers, re-provisioning, and manual records. Stop joining on hope: build a crosswalk table from every reliable bridge (billing customer id, domain, legacy id fields), measure match rates per bridge, and join through the crosswalk with unmatched accounts reported, not dropped.

```text
agent failed to join usage data with CRM records: account IDs mismatched
```

## Use this when
- Join coverage is well below the known account count
- The unmatched set includes large, real customers
- Ids differ in format, prefix, or system across the two sources

## Not for this skill when
- Coverage loss is small and explained by test or deleted accounts
- The usage data itself is missing upstream for those accounts

## Steps
1. Compute match rates joining on each candidate key: native id, billing id, domain, and legacy fields. Verify: the best and worst bridges are quantified
2. Sample unmatched accounts and find manually how each is represented in the other system. Verify: the mismatch patterns (prefixes, merged ids, typos) are characterised
3. Build a crosswalk table encoding those patterns as data, with a match-method column per row. Verify: the crosswalk covers the previously unmatched population
4. Re-run the join through the crosswalk and reconcile the final coverage against the CRM account count. Verify: coverage reaches the expected level or the residual is a named list
5. Add new-account crosswalk creation to provisioning so the map never falls behind again. Verify: future accounts join from day one

## Variant phrasings
### usage CRM join account ids mismatch
A related phrasing for the same underlying problem.
### crosswalk for account identifiers
A related phrasing for the same underlying problem.
### join coverage low between systems
A related phrasing for the same underlying problem.

Compatibility: Compatibility: warehouse joins across product analytics, billing, and Salesforce or HubSpot account tables, current versions.

## Why it happens
Identity is a dataset, not a join condition. Treating the mapping as maintained data with provenance per row turns an endless series of join patches into one asset that improves, and coverage metrics turn silent loss into a number someone owns.

## Edge cases / pitfalls
- Domain bridges fail for subsidiaries sharing a parent domain. Combine domain with name or billing evidence for those.
- Merged CRM accounts need many-to-one crosswalk rows with effective dates, or history joins break.
- Never overwrite source ids with mapped ids. Crosswalk alongside, so mapping errors stay reversible.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_jlhFUJUmYy3LUHz1taoTpw
