Match profile reference
Every option a match profile can use.
Profile settings
| Setting | Meaning |
|---|---|
| Entity type | The type this profile matches. One profile is active per entity type at a time. |
| Auto-link threshold | Composite weight at or above which a pair merges unattended. Log2 evidence units. Default 10.0, range 0–100. |
| Clerical review threshold | Composite weight at or above which a pair is queued for review. Must be at or below the auto-link threshold — enforced when you save. Default 5.0, range 0–100. |
| Prior match probability | The assumed share of candidate pairs that are true matches. Affects only the reported confidence figure — thresholds compare against the composite weight. Default 0.00001. |
| Minimum agreeing attributes | Distinct attributes that must agree before auto-linking, unless a deterministic level settled it. Threshold-independent. Default 1, range 1–20. |
| Active | Exactly one profile per entity type may be active. Activating one deactivates its siblings atomically. |
Comparators
Used by comparison levels to grade how well two values agree.
| Comparator | Compares | Notes |
|---|---|---|
exact | Equality of canonical values | The only comparator a deterministic level may use |
jaro_winkler | String similarity, favouring shared prefixes | Well suited to personal names |
levenshtein | Edit distance | Typos and transcription errors |
prefix | A leading substring | Truncated or abbreviated values |
last_n | The final n characters | Identifiers where only a suffix is retained |
phonetic | How values sound | Takes a codec — see below |
equivalence_set | Membership of a known-equivalent group | Nicknames and abbreviations, via a named dictionary |
token_aligned | Values as sets of tokens, order-independent | Reordered multi-part names |
date_equal | Two dates for equality | |
date_within | Two dates within a tolerance | Takes an amount and a unit |
numeric_equal | Two numbers for equality | |
numeric_within | Two numbers within a tolerance | Takes a delta and a unit |
lookup_equal | Two reference-data codes | Compares canonical codes, not labels |
address_component | One named part of a composite address | Composite-aware |
address_expand | Whole addresses, after expansion | Composite-aware |
null_handling | How a missing value is treated | |
multi_valued_best | Wraps another comparator across multi-value attributes | Rarely needed — multi-value attributes are enumerated automatically |
A scalar comparator applied to a whole composite attribute — an address, a licence — is rejected when the profile is saved. Two entirely different composites would otherwise compare as equal, which over-merges catastrophically. Target a named sub-field instead, or use a composite-aware comparator.
Blocking primitives
Used by blocking strategies to derive candidate-gathering keys.
| Primitive | Emits |
|---|---|
exact | The canonical value as a key |
prefix | A leading substring of the value |
phonetic | A phonetic encoding — takes a codec |
year_of | The year part of a date |
concat | One key combining several child primitives |
any_of | The union of several child primitives' keys |
trigram_gin | A similarity-based fallback rather than an equality key |
Multi-value attributes fan out: one key per value. A composite combines across its children, and is suppressed entirely if every contributing value is suppressed as anonymous.
Blocking strategy fields
A strategy wraps a tree of the primitives above. It accepts four fields, and none of them is fixed after creation.
| Field | Accepts | Default | What it does |
|---|---|---|---|
strategyName | 1–40 chars | — | Names the strategy, so a profile with several can be reasoned about. |
primitiveTree | A tree of primitives | — | Which keys this strategy derives. A malformed tree is refused when you save rather than silently gathering nothing. |
anonSuppress | true or false | false | Whether values too common to be evidence are dropped from this strategy's keys. See below. |
sortOrder | Integer, 0 or greater | 0 | Presentation order among the profile's strategies. |
A profile normally carries several strategies. Each derives its own keys, and a record is a candidate if any of them matches — so strategies add recall rather than narrowing each other.
anonSuppress on for strategies keyed on a common valueIt defaults to off, which means a strategy blocking on a surname alone will gather every Smith in the tenant as a candidate for every other Smith. That is not wrong — they genuinely share the key — but it is expensive and produces nothing the scoring can use.
With suppression on, values that appear too often to distinguish anyone stop producing keys for that strategy. Leave it off for strategies keyed on something already selective, such as a national identifier or a postcode combined with a surname.
Phonetic codecs
| Codec | Notes |
|---|---|
soundex | Classic, aggressive; high recall, low precision |
dmetaphone | Double metaphone; handles non-English name origins substantially better |
These two are the complete set. A codec name outside this list emits no keys at all — silently producing a blocking strategy that never gathers anything.
Survivorship strategies
Choose the winning value per attribute after a merge.
| Strategy | Winner | Winners per group |
|---|---|---|
source_priority | The value from the highest-ranked source system | 1 |
most_recent | The most recently updated value. Engine default when no rule is set. | 1 |
oldest_value | The value from the earliest contributing record | 1 |
max | The numeric or ordered maximum | 1 |
min | The numeric or ordered minimum | 1 |
frequency | The most common value across contributors | 1 |
aggregation | Every distinct value, deduplicated | Many |
Rules apply per (attribute, value type) group, so a multi-value attribute
with usage types resolves each type independently — one winning home address
and one winning work address, not one address overall.
aggregation is the right choice for genuinely multi-value attributes such as
email and phone, where collapsing to a single winner loses real data.

Comparison levels
A comparison level — a rung of a ladder — is what grades one attribute. These are the fields each rung accepts.
| Field | Accepts | Default | Changeable | What it does |
|---|---|---|---|---|
attributeName | 1–100 chars. A plain attribute name, or a dotted path into a composite | — | No | Which attribute this rung grades. address.postalCode targets a sub-field; a sub-field that the composite does not declare is refused when you save. A rung cannot be moved to a different attribute — create a new one. |
levelName | 1–40 chars | — | Yes | The rung's label, as in exact, phonetic, mismatch. |
levelOrder | Integer, 0 or greater | — | Yes | Position in the ladder. The engine walks in ascending order and takes the first rung that fits, so ordering is behaviour, not presentation. |
comparator | Up to 40 chars, or empty | — | Yes | How the two values are graded. Leaving it empty marks the catch-all rung that records a disagreement. |
comparatorConfig | An object | {} | Yes | That comparator's own settings. The shape differs per comparator — see Comparators. |
mProbability | 0 to 1 | — | Yes | How reliably this rung fires when two records really are the same. |
uProbability | 0 to 1 | — | Yes | How often it fires by pure coincidence. |
isDeterministic | true or false | false | Yes | Settles the pair on its own, regardless of the total. Legal only with the exact comparator. |
The weight is not yours to set
There is no weight field, and its absence is deliberate. The platform computes it from the two probabilities when you save the rung:
matchWeight = log2(mProbability / uProbability)
If the interface accepted a weight, the number on screen could disagree with the number the engine scores with. Instead you state what you believe about the evidence — how reliable the agreement is, and how often it happens by chance — and the weight follows.
Three further values are returned but never set: the resolved sub-field, the resolved attribute, and the weight itself.
Rules the platform enforces
- Levels are ordered; the engine takes the first that fits.
- Every ladder must end in a catch-all level, which is what records a disagreement. Without it a mismatch contributes nothing rather than counting against the pair.
- A level may be marked deterministic only when its comparator is
exact. - A ladder may target a composite sub-field using dotted notation. A sub-field that does not exist is rejected when the profile is saved, rather than silently scoring nothing.
- An edit must change at least one field; an empty change is refused rather than accepted as a no-op.
Next
Last verified against commit 315eb047 (2026-08-03)