Limit Rules
Limit rules cap how many distinct source records may share a single identifier value. They exist because real source data always contains at least one value that is not an identity — a placeholder email, a support inbox, a bot’s cookie, an empty-string surrogate — and without a cap, every record carrying that value merges into one profile.
Why Limit Rules Matter
Suppose noreply@company.com appears on 50,000 records. The email merge rule links records that share an email, so with no cap it links all 50,000 into a single profile. That profile is not a person, and everything downstream of it — audiences, journeys, suppression — is wrong.
A limit rule on the email family with a maximum of 100 says: an email value shared by more than 100 distinct records is not an identity signal. Those records contribute no email edges. They can still be linked by any other identifier they share.
A capped value does not make records disappear. Each one still resolves — as its own profile, or merged via a different identifier family. Only the over-shared value stops linking them.
Every Enabled Merge Rule Is Capped
Each merge rule family gets a cap whether or not you configure one:
| Configuration | Effective cap |
|---|---|
| No limit rule for the family | 100 (the default) |
Limit rule with max unique values = 25 | 25 |
Limit rule with max unique values = 0 | Unlimited — you have deliberately turned the cap off |
The graph detail page’s Limit Rules table lists every enabled family with its effective cap and whether that cap is Configured or Default, so the value the resolver actually enforces is always visible.
Setting a family to 0 removes its only protection against a shared value collapsing unrelated people into one profile. Prefer raising the number to disabling the cap.
What a Limit Rule Controls
There is one kind of limit rule: maximum distinct records per identifier value, configured per identifier family.
| Setting | Description |
|---|---|
| Identifier family | Which family the cap applies to (email, phone, user_id, cookie_id, …) |
| Max unique values | How many distinct source records may share one value in that family before it is ignored |
The cap is on one value, not on a profile. A profile can legitimately end up with many emails by chaining through other identifiers; what the rule prevents is a single value acting as a hub.
Choosing a Number
| Family | Typical range | Why |
|---|---|---|
email | 10–100 | Household and shared-inbox addresses are the usual offenders |
phone | 5–50 | Support and store numbers appear on many records |
user_id | 50–500 | Should be near-unique; a high count usually means a placeholder value |
cookie_id | 20–200 | Shared or reset devices inflate counts legitimately |
Measure before you choose. This query gives the distribution of how widely each value is shared, which is exactly what the cap compares against:
SELECT shared_by, COUNT(*) AS values_at_this_level
FROM (
SELECT LOWER(TRIM(email)) AS value, COUNT(DISTINCT id) AS shared_by
FROM crm_contacts
WHERE email IS NOT NULL AND TRIM(email) <> ''
GROUP BY 1
) _dist
GROUP BY shared_by
ORDER BY shared_by DESC
LIMIT 50;A healthy family has a long tail at shared_by = 1 and a handful of outliers. Set the cap above the legitimate cluster sizes and below the outliers.
How Limits Are Enforced
The cap is applied in two places, and the first is the one that matters.
During edge building. Each identifier value’s group size is computed as the edges are written, and groups larger than the cap emit no edges at all. This is the only placement that can prevent a super-node: a cap applied afterwards has to let the rows be written before it can delete them, and for a value shared by tens of thousands of records, writing them is the step that does not complete.
After edge building. A second pass deletes edges for over-shared values. Deterministic edges were already capped above, so what this catches is probabilistic edges, which are scored pair by pair and therefore cannot carry a group-size condition while being built.
Incremental runs apply the same cap, so a delta run can never reintroduce a group the full run refused to build.
Limits Drop Edges, They Do Not Split Profiles
Limit rules work by preventing edges from being created, not by breaking up profiles after the fact. Merge rule priority does not change the outcome — edges are a set, and the same edges are produced whichever order the rules are compiled in. Priority decides which family is resolved first, not which one wins.
Symptoms and Tuning
| What you see | Likely cause | What to do |
|---|---|---|
| Profiles that should be one person are separate | Cap too tight for a family whose values are legitimately shared | Raise that family’s max unique values |
| One profile contains obviously unrelated people | Cap too loose, or a shared value just under it | Lower the cap, or clean the placeholder value at the source |
| Profile count barely drops after resolution | Caps are suppressing most edges | Check the distribution query above — a cap below your typical cluster size suppresses everything |
| A run that used to finish now produces fewer merges | The default cap now applies to a family that previously ran uncapped | Configure an explicit limit rule for it |
The most durable fix is usually upstream: a placeholder identifier that trips the cap is a data quality problem, and excluding it in the model’s SQL is better than tuning around it.
Related
- Merge Rules — Which identifiers create links
- Identifier Families — How variants normalise into one comparable value
- Running Resolution — Executing and monitoring runs
- Profile Explorer — Inspecting how a profile was assembled