<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RudderStack Docs – Advanced ID Stitcher Features</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/</link><description>Recent content in Advanced ID Stitcher Features on RudderStack Docs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/index.xml" rel="self" type="application/rss+xml"/><item><title>Archive: ID Graph Inclusion/Exclusion Rules</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/</guid><description>
&lt;p>The ID graph exclusions/inclusions feature lets you determine which nodes and edges are included in your ID graph by defining rules in a warehouse table—giving you fine-grained control over the graph structure beyond what&amp;rsquo;s possible with regex-based filters.&lt;/p>
&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">These rules take the highest precedence over any other filtering mechanisms, including regex filters and rule-based filters.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="key-features" data-heading="Key features" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h2 id="key-features">Key features&lt;/h2>&lt;ul>
&lt;li>&lt;strong>Node control&lt;/strong>: Exclude or include specific nodes (identifiers) in the ID graph.&lt;/li>
&lt;li>&lt;strong>Edge control&lt;/strong>: Define specific connections between the identifiers to exclude or include.&lt;/li>
&lt;li>&lt;strong>Rule management&lt;/strong>: Get CLI tools for creating and populating rules tables.&lt;/li>
&lt;li>&lt;strong>Precedence control&lt;/strong>: Specify how conflicting rules should be handled.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="set-up-the-rules-table" data-heading="Set up the rules table" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h2 id="set-up-the-rules-table">Set up the rules table&lt;/h2>&lt;p>This section describes how to create and populate the rules table that controls ID Graph inclusions and exclusions.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="1-create-the-rules-table" data-heading="1. Create the rules table" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h3 id="1-create-the-rules-table">1. Create the rules table&lt;/h3>&lt;p>Use the following CLI command to create a dedicated table in your warehouse:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pb idstitch rules create
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This creates a table named &lt;code>id_stitch_rules&lt;/code> by default. You can specify a custom name as follows:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pb idstitch rules create --name my_custom_rules
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="2-add-rules-to-this-table" data-heading="2. Add rules to this table" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h3 id="2-add-rules-to-this-table">2. Add rules to this table&lt;/h3>&lt;p>You can add rules in two ways:&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="interactive-mode" data-heading="Interactive mode" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h4 id="interactive-mode">Interactive mode&lt;/h4>&lt;p>Run the following command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pb idstitch rules update --interactive
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You will then be prompted to enter the following details:&lt;/p>
&lt;ul>
&lt;li>Entity name (for example, &lt;code>user&lt;/code>, &lt;code>account&lt;/code>)&lt;/li>
&lt;li>ID1 value and type&lt;/li>
&lt;li>Optional ID2 value and type&lt;/li>
&lt;li>Action (EXCLUDE or INCLUDE)&lt;/li>
&lt;li>Optional reason for the action&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="batch-mode" data-heading="Batch mode" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h4 id="batch-mode">Batch mode&lt;/h4>&lt;p>Run the following command:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pb idstitch rules update -f rules.csv
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This &lt;code>rules.csv&lt;/code> file will contain the required columns: &lt;code>entity&lt;/code>, &lt;code>id1&lt;/code>, &lt;code>id1_type&lt;/code>, &lt;code>action&lt;/code>, and optional columns: &lt;code>id2&lt;/code>, &lt;code>id2_type&lt;/code>, &lt;code>reason&lt;/code>.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="configure-your-project-yaml" data-heading="Configure your project YAML" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h2 id="configure-your-project-yaml">Configure your project YAML&lt;/h2>&lt;p>To enable the rules for your project, add the following configuration to your YAML file:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Existing configuration...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">entities&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">user&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id_stitcher&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/rudder_user_id_stitcher&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># Other entity configuration&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># Add the id_stitcher_rules section&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_stitcher_rules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">enabled&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Optional, defaults to false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">table_name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">id_stitch_rules &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Optional, defaults to id_stitch_rules&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">priority&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">exclude &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Optional, defaults to exclude&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="configuration-parameters" data-heading="Configuration parameters" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h3 id="configuration-parameters">Configuration parameters&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Parameter&lt;/th>
&lt;th style="text-align:left">Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">&lt;code>enabled&lt;/code>&lt;/td>
&lt;td style="text-align:left">Set it to &lt;code>true&lt;/code> to activate the rules feature.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;code>table_name&lt;/code>&lt;/td>
&lt;td style="text-align:left">The name of your rules table. It defaults to &lt;code>id_stitch_rules&lt;/code>.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;code>priority&lt;/code>&lt;/td>
&lt;td style="text-align:left">Defines how to handle conflicting rules. Acceptable values are &lt;code>exclude&lt;/code> and &lt;code>include&lt;/code>. The default value is &lt;code>exclude&lt;/code>.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="rule-behavior-and-examples" data-heading="Rule behavior and examples" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h2 id="rule-behavior-and-examples">Rule behavior and examples&lt;/h2>&lt;p>Note that the rules fall into two categories:&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="1-single-id-rules-node-rules" data-heading="1. Single ID rules (Node rules)" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h3 id="1-single-id-rules-node-rules">1. Single ID rules (Node rules)&lt;/h3>&lt;p>These rules apply to a single identifier and affect the entire node.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-exclude-a-test-email" data-heading="Example: Exclude a test email" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h4 id="example-exclude-a-test-email">Example: Exclude a test email&lt;/h4>&lt;pre tabindex="0">&lt;code>Entity: user
ID1: test@company.com
ID1_Type: email
Action: EXCLUDE
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Effect&lt;/strong>: The node for &lt;code>test@company.com&lt;/code> will be completely removed from the ID graph.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-include-a-specific-user-id" data-heading="Example: Include a specific user ID" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h4 id="example-include-a-specific-user-id">Example: Include a specific user ID&lt;/h4>&lt;pre tabindex="0">&lt;code>Entity: user
ID1: 12345
ID1_Type: user_id
Action: INCLUDE
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Effect&lt;/strong>: The node for user_id &lt;code>12345&lt;/code> will be added to the graph even if it doesn&amp;rsquo;t appear in the input data.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="2-paired-id-rules-edge-rules" data-heading="2. Paired ID rules (Edge rules)" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h3 id="2-paired-id-rules-edge-rules">2. Paired ID rules (Edge rules)&lt;/h3>&lt;p>These rules apply to the connections between two identifiers.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-exclude-a-specific-connection" data-heading="Example: Exclude a specific connection" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h4 id="example-exclude-a-specific-connection">Example: Exclude a specific connection&lt;/h4>&lt;pre tabindex="0">&lt;code>Entity: user
ID1: john@example.com
ID1_Type: email
ID2: user_67890
ID2_Type: user_id
Action: EXCLUDE
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Effect&lt;/strong>: The direct connection between &lt;code>john@example.com&lt;/code> and &lt;code>user_67890&lt;/code> will be removed but both nodes remain in the ID graph. You can still connect them through other paths.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-include-a-specific-connection" data-heading="Example: Include a specific connection" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h4 id="example-include-a-specific-connection">Example: Include a specific connection&lt;/h4>&lt;pre tabindex="0">&lt;code>Entity: user
ID1: jane@example.com
ID1_Type: email
ID2: user_54321
ID2_Type: user_id
Action: INCLUDE
&lt;/code>&lt;/pre>&lt;p>&lt;strong>Effect&lt;/strong>: A direct connection between &lt;code>jane@example.com&lt;/code> and &lt;code>user_54321&lt;/code> will be added to the ID graph &lt;strong>even if&lt;/strong> this connection doesn&amp;rsquo;t exist in the input data.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="conflict-resolution" data-heading="Conflict resolution" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h2 id="conflict-resolution">Conflict resolution&lt;/h2>&lt;p>When rules conflict, the resolution depends on your &lt;a href="#configuration-parameters" >&lt;code>priority&lt;/code>&lt;/a> setting:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>With &lt;code>priority: exclude&lt;/code> (default)&lt;/strong>: If a node is excluded but appears in an edge inclusion rule, the node exclusion takes precedence and the edge inclusion is discarded.&lt;/li>
&lt;li>&lt;strong>With &lt;code>priority: include&lt;/code>&lt;/strong>: If a node is excluded but appears in an edge inclusion rule, the edge inclusion takes precedence and the node will remain in the graph.&lt;/li>
&lt;/ul>
&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">If multiple rules exist for the same entity and identifiers, the most recent rule takes precedence.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="how-this-feature-works" data-heading="How this feature works" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" data-title="ID Graph Inclusion/Exclusion Rules" -->
&lt;h2 id="how-this-feature-works">How this feature works&lt;/h2>&lt;ol>
&lt;li>During &lt;code>pb run&lt;/code> or &lt;code>pb compile&lt;/code>, the system checks for any &lt;a href="#configure-your-project-yaml" >enabled rules&lt;/a>.&lt;/li>
&lt;li>Rules are applied while preparing the &lt;code>raw_edges&lt;/code> table. Note that excluded nodes are not added to this &lt;code>raw_edges&lt;/code> table.&lt;/li>
&lt;/ol>
&lt;br /></description></item><item><title>Archive: ID Graph Cardinality Rules</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/</guid><description>
&lt;p>This guide explains how to use cardinality rules to limit the maximum number of connections between different ID types in your identity graph.&lt;/p>
&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>Cardinality rules are supported for &lt;strong>Snowflake&lt;/strong> and &lt;strong>BigQuery&lt;/strong>.&lt;/p>
&lt;p>Rule enforcement, the &lt;code>&amp;lt;material&amp;gt;_&amp;lt;entity&amp;gt;_CARDINALITY_AUDIT&lt;/code> table, and the per-edge &lt;code>cardinality_info&lt;/code> metadata are emitted on both warehouses.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="overview" data-heading="Overview" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="overview">Overview&lt;/h2>&lt;p>ID Graph cardinality rules let you define maximum connection limits between different ID types in your identity graph, providing fine-grained control over how identities are stitched together.&lt;/p>
&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>Cardinality rules help prevent identity explosion and maintain data quality by limiting how many connections a node of one type can have to nodes of another type.&lt;/p>
&lt;p>This is particularly useful for maintaining data quality when dealing with shared identifiers like email addresses, device IDs, or anonymous IDs that might be used across multiple users.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;p>Cardinality rules work seamlessly with other Profiles features:&lt;/p>
&lt;ul>
&lt;li>Input &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/pb-project-yaml/id-types/" >filters&lt;/a> reduce data volume before graph processing. The cardinality enforcement step comes after this in the pipeline, so if expected nodes are missing from your graph, input filters can be the reason.&lt;/li>
&lt;li>Manual &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-rules/" >exclusion/inclusion rules&lt;/a> provide explicit control over specific connections and happen after the cardinality enforcement step in the pipeline. If you find identity clusters that violate cardinality rules despite having the rules configured, those extra edges might be coming from manual inclusion overrides.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="key-features" data-heading="Key features" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="key-features">Key features&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Data quality&lt;/strong>: You can prevent identity graphs from becoming overly connected due to shared or recycled identifiers.&lt;/li>
&lt;li>&lt;strong>Performance&lt;/strong>: Maintain optimal graph size by controlling edge proliferation.&lt;/li>
&lt;li>&lt;strong>Compliance&lt;/strong>: Enforce business rules about identity relationships.&lt;/li>
&lt;li>&lt;strong>Transparency&lt;/strong>: Get full audit trail of which edges were filtered and why.&lt;/li>
&lt;li>&lt;strong>Incremental consistency&lt;/strong>: Historical violations persist across runs for reliable behavior.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="performance-considerations" data-heading="Performance considerations" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="performance-considerations">Performance considerations&lt;/h3>&lt;p>Consider the following when implementing cardinality rules:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Initial runs&lt;/strong> may experience increased runtime as the system processes and enforces the new rules across your entire dataset.&lt;/li>
&lt;li>&lt;strong>Incremental runs&lt;/strong> should see minimal performance impact once the rules are established.&lt;/li>
&lt;li>&lt;strong>Trade-off evaluation&lt;/strong>: The increased runtime in initial runs delivers more precise ID stitching and better data quality. Evaluate whether the improved accuracy justifies the additional processing time for your use case.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="how-cardinality-rules-work" data-heading="How cardinality rules work" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="how-cardinality-rules-work">How cardinality rules work&lt;/h2>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="directional-rules" data-heading="Directional rules" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="directional-rules">Directional rules&lt;/h3>&lt;p>Cardinality rules are &lt;strong>directional&lt;/strong> — they apply from a source ID type to a target ID type. For example:&lt;/p>
&lt;ul>
&lt;li>&lt;code>user_id → email: max_edges = 2&lt;/code> means each &lt;code>user_id&lt;/code> can connect to at most 2 &lt;code>email&lt;/code>.&lt;/li>
&lt;li>Note that this does not limit how many &lt;code>user_id&lt;/code> an &lt;code>email&lt;/code> can connect to (unless you add a separate rule)&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="rule-enforcement" data-heading="Rule enforcement" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="rule-enforcement">Rule enforcement&lt;/h3>&lt;p>When a rule is violated:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>All edges&lt;/strong> from the violating source are removed (not just the excess ones)&lt;/li>
&lt;li>&lt;strong>Nodes are preserved&lt;/strong> as isolated stubs to maintain graph integrity&lt;/li>
&lt;li>&lt;strong>Violations are audited&lt;/strong> with full details about what was removed and why&lt;/li>
&lt;li>&lt;strong>Historical context&lt;/strong> is maintained across incremental runs&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="incremental-behavior" data-heading="Incremental behavior" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="incremental-behavior">Incremental behavior&lt;/h3>&lt;p>The feature works seamlessly with incremental runs:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Historical violations persist&lt;/strong>: If a node violated a rule previously, new edges to that node type are automatically blocked.&lt;/li>
&lt;li>&lt;strong>New violations break all edges&lt;/strong>: If a new edge causes a violation, all current edges from that source are removed.&lt;/li>
&lt;li>&lt;strong>Rule removal&lt;/strong>: If you remove a rule from your configuration, the entire id graph is built from scratch, so historical violations for that rule are no longer enforced.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="configuration" data-heading="Configuration" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="configuration">Configuration&lt;/h2>&lt;p>You can add cardinality rules to your &lt;code>pb_project.yaml&lt;/code> under the &lt;code>id_types&lt;/code> section, as shown:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">entities&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">user&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id_stitcher&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/customer_id_graph&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">user_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="l">anonymous_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">user_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">email&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">anonymous_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">anonymous_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">email&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="configuration-limits" data-heading="Configuration limits" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="configuration-limits">Configuration limits&lt;/h3>&lt;p>The following limits ensure optimal performance for incremental runs:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Maximum edges per rule&lt;/strong>: 10 (The &lt;code>maximum_edges&lt;/code> value for each rule cannot exceed 10)&lt;/li>
&lt;li>&lt;strong>Maximum target types per source&lt;/strong>: 5 (The &lt;code>maximum_edges&lt;/code> list for each source ID type cannot have more than 5 entries)&lt;/li>
&lt;/ul>
&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">The above limits only apply when using cardinality rules. Without these rules, the regular ID stitcher can connect unlimited edges, as usual.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="examples" data-heading="Examples" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="examples">Examples&lt;/h3>&lt;p>This section provides examples of how to configure cardinality rules for different use cases:&lt;/p>
&lt;nav>
&lt;div class="nav nav-tabs" id="nav-tab" role="tablist">
&lt;a class="nav-item nav-link active "
id="nav-cfbdae" data-toggle="tab" href="#cfbdae"
role="tab" aria-controls="nav-home" aria-selected="true">Ecommerce platform&lt;/a>
&lt;a class="nav-item nav-link "
id="nav-deafcb" data-toggle="tab" href="#deafcb"
role="tab" aria-controls="nav-home" aria-selected="true">Marketing platform&lt;/a>
&lt;/div>
&lt;/nav>
&lt;div class="tab-content" id="nav-tab-content">
&lt;div class="tab-pane fade show active " id="cfbdae" role="tabpanel" aria-labelledby="nav-1">
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">user_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">email&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Users can have up to 2 emails&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">device_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">5&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Users can have up to 5 devices&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Each email belongs to only 1 user&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">device_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Shared devices (family tablets)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>
&lt;div class="tab-pane fade show " id="deafcb" role="tabpanel" aria-labelledby="nav-1">
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">anonymous_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">email&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Anonymous sessions link to 1 email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Emails don&amp;#39;t get shared between users&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;/div>
&lt;/div>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="how-rule-application-works" data-heading="How rule application works" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="how-rule-application-works">How rule application works&lt;/h2>&lt;p>This section explains how cardinality rules are applied to your identity graph.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="fresh-and-incremental-runs" data-heading="Fresh and incremental runs" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="fresh-and-incremental-runs">Fresh and incremental runs&lt;/h3>&lt;p>Cardinality rules behave differently depending on whether you&amp;rsquo;re running a fresh or incremental run:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Fresh runs&lt;/strong>: Rules are applied to all incoming data. If a node stays within its limits, all edges are preserved.&lt;/li>
&lt;li>&lt;strong>Incremental runs&lt;/strong>: Rules consider historical violations. If a node previously violated a rule or if new data causes a violation, all edges from that source are removed, including previously valid ones.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="fresh-run" data-heading="Fresh run" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="fresh-run">Fresh run&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Input data&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">user_1 → email_a&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">user_1 → email_b # Valid&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">within limit of 2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># Result: Both edges allowed&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="incremental-run" data-heading="Incremental run" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="incremental-run">Incremental run&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Previous run: user_1 had 2 emails (at limit)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># New data: &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">user_1 → email_c &lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># This causes violation&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># Result: ALL edges from user_1 are broken (including previous ones)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example" data-heading="Example" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="example">Example&lt;/h3>&lt;p>Given these rules:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">user_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">email&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And the following data:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="l">user_1 ↔ email@example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">user_2 ↔ email@example.com &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">user_3 ↔ email@example.com&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>What happens&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>&lt;code>email@example.com&lt;/code> connects to 3 user_ids, violating the &lt;code>email → user_id: 1&lt;/code> rule&lt;/li>
&lt;li>&lt;strong>All three connections&lt;/strong> are broken, not just the excess ones.&lt;/li>
&lt;li>All nodes are preserved as isolated stubs.&lt;/li>
&lt;li>Three audit entries are created documenting the violation.&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="monitoring-and-debugging" data-heading="Monitoring and debugging" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="monitoring-and-debugging">Monitoring and debugging&lt;/h2>&lt;p>This section explains how to monitor and debug cardinality rules.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="cardinality-audit-table" data-heading="Cardinality Audit table" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="cardinality-audit-table">Cardinality Audit table&lt;/h3>&lt;p>Each violation is logged in the cardinality audit table, which resides in the same schema as the ID Stitcher output tables. The table name is derived by appending the suffix &lt;code>_CARDINALITY_AUDIT&lt;/code> to the name of the ID Stitcher model.&lt;/p>
&lt;p>The audit table is created on both Snowflake and BigQuery and contains the following columns:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Column&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>run_id&lt;/code>&lt;/td>
&lt;td>ID of the run when the violation occurred.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>model_hash&lt;/code>&lt;/td>
&lt;td>Hash of the model configuration.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>id1&lt;/code>&lt;/td>
&lt;td>Source ID value.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>id1_type&lt;/code>&lt;/td>
&lt;td>Source ID type.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>id2&lt;/code>&lt;/td>
&lt;td>Target ID value.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>id2_type&lt;/code>&lt;/td>
&lt;td>Target ID type.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>reason&lt;/code>&lt;/td>
&lt;td>Always &lt;code>&amp;quot;CARDINALITY_VIOLATION&amp;quot;&lt;/code>.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>rule_details&lt;/code>&lt;/td>
&lt;td>JSON with &lt;code>max_edges&lt;/code> and &lt;code>current_count&lt;/code>.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>source_models&lt;/code>&lt;/td>
&lt;td>JSON array (BigQuery) or native ARRAY (Snowflake). Each element is &lt;code>{source_model, first_seen_at}&lt;/code> and records every input model that contributed the dropped edge, with the earliest timestamp at which that model first observed it.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="sample-rows" data-heading="Sample rows" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="sample-rows">Sample rows&lt;/h4>&lt;p>The following rows are excerpted from a &lt;code>qa_metadata_validation_user_CARDINALITY_AUDIT&lt;/code> table after a run where two users (&lt;code>viol_user&lt;/code> and &lt;code>mviol_user&lt;/code>) each exceeded a &lt;code>user_id → email: max_edges = 2&lt;/code> rule. &lt;code>mviol_user&lt;/code> saw one of the violator emails (&lt;code>mviol_shared@test.com&lt;/code>) from two different input models, which is why its &lt;code>source_models&lt;/code> array has two entries:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">id1, id1_type, id2, id2_type, model_hash, reason, rule_details, run_id, source_models
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">viol_user, user_id, viol_a@test.com, email, ffffe585, CARDINALITY_VIOLATION, {&amp;#34;current_count&amp;#34;:3,&amp;#34;max_edges&amp;#34;:2}, 1, [{&amp;#34;source_model&amp;#34;:&amp;#34;events_app&amp;#34;,&amp;#34;first_seen_at&amp;#34;:&amp;#34;2022-03-01 10:00:00.000&amp;#34;}]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">viol_user, user_id, viol_b@test.com, email, ffffe585, CARDINALITY_VIOLATION, {&amp;#34;current_count&amp;#34;:3,&amp;#34;max_edges&amp;#34;:2}, 1, [{&amp;#34;source_model&amp;#34;:&amp;#34;events_app&amp;#34;,&amp;#34;first_seen_at&amp;#34;:&amp;#34;2022-03-01 10:00:01.000&amp;#34;}]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">viol_user, user_id, viol_c@test.com, email, ffffe585, CARDINALITY_VIOLATION, {&amp;#34;current_count&amp;#34;:3,&amp;#34;max_edges&amp;#34;:2}, 1, [{&amp;#34;source_model&amp;#34;:&amp;#34;events_app&amp;#34;,&amp;#34;first_seen_at&amp;#34;:&amp;#34;2022-03-01 10:00:02.000&amp;#34;}]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">mviol_user, user_id, mviol_shared@test.com, email, ffffe585, CARDINALITY_VIOLATION, {&amp;#34;current_count&amp;#34;:3,&amp;#34;max_edges&amp;#34;:2}, 1, [{&amp;#34;source_model&amp;#34;:&amp;#34;events_app&amp;#34;,&amp;#34;first_seen_at&amp;#34;:&amp;#34;2022-04-01 10:00:00.000&amp;#34;},{&amp;#34;source_model&amp;#34;:&amp;#34;events_web&amp;#34;,&amp;#34;first_seen_at&amp;#34;:&amp;#34;2022-03-25 08:00:00.000&amp;#34;}]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="cardinality_info-in-the-metadata-column" data-heading="&lt;code>cardinality_info&lt;/code> in the metadata column" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="cardinality_info-in-the-metadata-column">&lt;code>cardinality_info&lt;/code> in the metadata column&lt;/h3>&lt;p>When edge metadata logging is enabled (see &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/identity-graph/#metadata-and-observability" >Metadata and observability&lt;/a>), the per-node &lt;code>METADATA&lt;/code> column on the ID stitcher output reflects rule enforcement in two ways:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Capped edges&lt;/strong> for non-violator nodes carry a &lt;code>cardinality_info&lt;/code> field on the stub edge, recording the &lt;code>max_edges&lt;/code> and &lt;code>current_count&lt;/code> that caused the cap.&lt;/li>
&lt;li>&lt;strong>Violator nodes&lt;/strong> (nodes that exceeded a rule and had all their edges removed) appear with an &lt;strong>empty&lt;/strong> &lt;code>direct_edge_info.edges_by_type&lt;/code> array. Their &lt;code>node_info&lt;/code> is preserved so the node still exists as an isolated stub in the graph.&lt;/li>
&lt;/ul>
&lt;p>For example, both a single-source violator (&lt;code>viol_user&lt;/code>) and a multi-source violator (&lt;code>mviol_user&lt;/code>) collapse to the same shape in the metadata column — only &lt;code>node_info&lt;/code> survives:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;direct_edge_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;edges_by_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;node_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;first_seen_at&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2022-04-01 10:00:00.000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;source_model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;events_app&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;first_seen_at&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2022-03-25 08:00:00.000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;source_model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;events_web&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Because dropped edges no longer appear in the metadata column, the audit table&amp;rsquo;s &lt;code>source_models&lt;/code> column is the only surviving trace of which input model contributed each violator edge. See &lt;a href="#6-interpret-the-audit-table" >Interpret the audit table&lt;/a> for a debugging workflow.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="best-practices" data-heading="Best practices" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="best-practices">Best practices&lt;/h2>&lt;p>This section provides best practices for configuring the cardinality rules correctly in your Profiles project.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="1-start-conservatively" data-heading="1. Start conservatively" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="1-start-conservatively">1. Start conservatively&lt;/h4>&lt;p>Begin with lower limits and gradually increase based on your data patterns:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Start here&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># Adjust based on audit results&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># If you see legitimate shared emails&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="2-monitor-audit-tables" data-heading="2. Monitor audit tables" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="2-monitor-audit-tables">2. Monitor audit tables&lt;/h4>&lt;p>Make sure to review the Cardinality Audit table regularly to understand:&lt;/p>
&lt;ul>
&lt;li>Which rules are triggering most often&lt;/li>
&lt;li>Whether legitimate connections are being blocked&lt;/li>
&lt;li>If limits need adjustment&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="3-test-with-historical-data" data-heading="3. Test with historical data" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="3-test-with-historical-data">3. Test with historical data&lt;/h4>&lt;p>Before deploying rules to production:&lt;/p>
&lt;ul>
&lt;li>Run rules against historical data in a test environment.&lt;/li>
&lt;li>Analyze the audit results.&lt;/li>
&lt;li>Adjust limits based on findings.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="4-consider-bidirectional-rules" data-heading="4. Consider bidirectional rules" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="4-consider-bidirectional-rules">4. Consider bidirectional rules&lt;/h4>&lt;p>Make sure to consider both directions of a relationship:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Often you want both directions&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">user_id&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">email&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Users can have multiple emails&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># But emails belong to one user&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="5-add-rules-for-shared-identifiers" data-heading="5. Add rules for shared identifiers" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="5-add-rules-for-shared-identifiers">5. Add rules for shared identifiers&lt;/h4>&lt;p>Cardinality rules help when a single identifier can legitimately appear across many users but you don&amp;rsquo;t want the graph to merge those users. Common cases:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Shared corporate emails&lt;/strong> such as &lt;code>info@&lt;/code>, &lt;code>support@&lt;/code>, or &lt;code>hr@&lt;/code> addresses that show up in many sessions.&lt;/li>
&lt;li>&lt;strong>Bot or test accounts&lt;/strong> that share a fixed &lt;code>anonymous_id&lt;/code> or &lt;code>device_id&lt;/code> across thousands of synthetic users.&lt;/li>
&lt;li>&lt;strong>Sentinel and placeholder values&lt;/strong> such as &lt;code>0&lt;/code>, &lt;code>unknown&lt;/code>, &lt;code>n/a&lt;/code>, or a default device identifier that slipped past upstream filters and would otherwise stitch unrelated users into one cluster.&lt;/li>
&lt;/ul>
&lt;p>If a few well-known sentinel values are responsible for most of the spread, prefer adding them to your input &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/pb-project-yaml/id-types/" >filters&lt;/a> so they never enter the graph in the first place. Cardinality rules are the right tool when the offending values are not known in advance and you need the graph itself to flag them.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="6-interpret-the-audit-table" data-heading="6. Interpret the audit table" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="6-interpret-the-audit-table">6. Interpret the audit table&lt;/h4>&lt;p>To triage cardinality violations:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Group by &lt;code>reason&lt;/code> and &lt;code>model_hash&lt;/code>&lt;/strong> to confirm the violations belong to the rule you expect. &lt;code>rule_details&lt;/code> carries the configured &lt;code>max_edges&lt;/code> value and the &lt;code>current_count&lt;/code> the source node reached, so a row with &lt;code>current_count: 12, max_edges: 2&lt;/code> is qualitatively different from one with &lt;code>current_count: 3, max_edges: 2&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Sort by &lt;code>id1&lt;/code> to find the worst offenders.&lt;/strong> A node that appears as &lt;code>id1&lt;/code> many times is over-connected on one or more target types; the count of distinct &lt;code>id2&lt;/code> values for that &lt;code>id1&lt;/code> reflects how many edges triggered the violation in the current run.&lt;/li>
&lt;li>&lt;strong>Use &lt;code>source_models&lt;/code> to trace each dropped edge back to its input.&lt;/strong> This is the only surviving source-attribution trace for violator edges, because the per-node &lt;code>direct_edge_info.edges_by_type&lt;/code> array is emptied when a node violates a rule. If a single &lt;code>id2&lt;/code> carries multiple &lt;code>source_models&lt;/code> entries, multiple input models independently reported the same edge — useful for deciding whether the offending edge is a data-quality problem in one source or a real cross-source pattern.&lt;/li>
&lt;li>&lt;strong>Cross-reference with the metadata column.&lt;/strong> For non-violator nodes that share an &lt;code>id2&lt;/code> with a violator, look at the &lt;code>cardinality_info&lt;/code> field on the stub edge to see whether the rule capped the edge or whether it survived intact.&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="7-trace-source-attribution-in-the-metadata-column" data-heading="7. Trace source attribution in the metadata column" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h4 id="7-trace-source-attribution-in-the-metadata-column">7. Trace source attribution in the metadata column&lt;/h4>&lt;p>For nodes that did not violate a rule, the metadata column carries full source attribution per edge. The &lt;code>direct_edge_info.edges_by_type[].edges[].sources[]&lt;/code> array lists every input model that contributed the edge, along with the timestamp each one first observed it. Combined with the audit table for violators, these two sources provide complete source-attribution coverage across the graph.&lt;/p>
&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/identity-graph/#metadata-and-observability" >Metadata and observability&lt;/a> for the full per-source contract.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="troubleshooting" data-heading="Troubleshooting" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Issue&lt;/th>
&lt;th style="text-align:left">Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left">Legitimate connections being blocked&lt;/td>
&lt;td style="text-align:left">Review audit table and increase limits if needed.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Identity graph still too connected&lt;/td>
&lt;td style="text-align:left">Add more restrictive rules or lower existing limits.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="debugging" data-heading="Debugging" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="debugging">Debugging&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Check rule configuration&lt;/strong> in &lt;code>pb_project.yaml&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Query audit table&lt;/strong> to see what is blocked.&lt;/li>
&lt;li>&lt;strong>Review stub metadata&lt;/strong> in the final ID graph.&lt;/li>
&lt;li>Compare &lt;strong>fresh vs. incremental&lt;/strong> run results.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="migration-guide" data-heading="Migration guide" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h2 id="migration-guide">Migration guide&lt;/h2>&lt;p>This section provides tips on managing cardinality rules in your Profiles models.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="enable-rules-on-existing-models" data-heading="Enable rules on existing models" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="enable-rules-on-existing-models">Enable rules on existing models&lt;/h3>&lt;ol>
&lt;li>&lt;strong>Add rules gradually&lt;/strong>: Start with one rule and observe effects&lt;/li>
&lt;li>&lt;strong>Test in development&lt;/strong>: Use a copy of production data to validate&lt;/li>
&lt;li>&lt;strong>Monitor after deployment&lt;/strong>: Watch audit tables and graph metrics&lt;/li>
&lt;li>&lt;strong>Adjust as needed&lt;/strong>: Fine-tune limits based on real-world results&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="disable-rules" data-heading="Disable rules" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/id-graph-cardinality-rules/" data-title="ID Graph Cardinality Rules" -->
&lt;h3 id="disable-rules">Disable rules&lt;/h3>&lt;p>To stop enforcing a rule, simply remove it from your configuration:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Before&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">maximum_edges&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">user_id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c"># After (rule removed)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">id_types&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">email&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c"># maximum_edges section removed&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">This triggers a complete fresh run of the model. Historical violations are no longer enforced, but previous audit records remain for reference.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html></description></item><item><title>Archive: Advanced ID Stitcher Operations</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/</guid><description>
&lt;p>This guide explains advanced operations available in the Profiles ID Stitcher, including the rebase incremental mode and how ID determinism ensures stable user identifiers across runs.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="the-rebase_incremental-flag" data-heading="The &lt;code>rebase_incremental&lt;/code> flag" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/" data-title="Advanced ID Stitcher Operations" -->
&lt;h2 id="the-rebase_incremental-flag">The &lt;code>rebase_incremental&lt;/code> flag&lt;/h2>&lt;p>While the ID Stitcher typically runs in &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/" >Incremental Mode&lt;/a> (processing only the data that arrived since the start of the last run and merging it with previous run&amp;rsquo;s graph), you can use a powerful reset mechanism called &lt;code>rebase_incremental&lt;/code>.&lt;/p>
&lt;html lang="en">
&lt;blockquote class="info">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/info.svg loading="lazy" alt="info" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">This flag is currently only available in the CLI.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="how-it-works" data-heading="How it works" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/" data-title="Advanced ID Stitcher Operations" -->
&lt;h3 id="how-it-works">How it works&lt;/h3>&lt;p>When you set this flag to &lt;code>true&lt;/code>, the pipeline changes behavior in three critical ways:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Ignores history&lt;/strong>: It does not load the previous mapping table (the graph state from the previous run).&lt;/li>
&lt;li>&lt;strong>Full ingestion&lt;/strong>: It removes the timestamp filters on the input tables, reading the &lt;strong>entire history&lt;/strong> of edges from the beginning of time.&lt;/li>
&lt;li>&lt;strong>Fresh calculation&lt;/strong>: It rebuilds every cluster and recalculates every user ID from scratch using the current logic.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="use-cases" data-heading="Use cases" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/" data-title="Advanced ID Stitcher Operations" -->
&lt;h3 id="use-cases">Use cases&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Applying new rules retroactively&lt;/strong>: If you update your blocklist (for example, adding a new spam IP), a standard incremental run only blocks future edges. A rebase applies this block to the entire history, splitting any clusters that were incorrectly merged by that IP in the past.&lt;/li>
&lt;li>&lt;strong>Graph reset&lt;/strong>: If the graph has become too &amp;ldquo;messy&amp;rdquo; (too many older, irrelevant edges), a rebase allows you to clean up the state based on current data retention policies.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="why-ids-are-deterministic" data-heading="Why IDs are deterministic" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/" data-title="Advanced ID Stitcher Operations" -->
&lt;h2 id="why-ids-are-deterministic">Why IDs are deterministic&lt;/h2>&lt;p>A common concern with re-running a graph algorithm is that IDs might shuffle (for example, user &lt;code>ABC&lt;/code> becomes user &lt;code>XYZ&lt;/code>). The ID Stitcher logic prevents this.&lt;/p>
&lt;p>&lt;strong>Logic used&lt;/strong>&lt;/p>
&lt;p>The user ID is not a random number — it is mathematically derived from the &lt;strong>anchor node&lt;/strong> of the cluster.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Anchor node&lt;/strong>: The node with the earliest &lt;code>occurred_at_col&lt;/code> timestamp in the cluster.&lt;/li>
&lt;li>&lt;strong>Formula used&lt;/strong>:&lt;/li>
&lt;/ul>
&lt;p>&lt;code>ID = ID_GEN_OPERATOR(ANCHOR_NODE_VALUE + ANCHOR_NODE_TYPE)&lt;/code>&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="why-ids-persist-during-incremental-runs" data-heading="Why IDs persist during incremental runs" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/" data-title="Advanced ID Stitcher Operations" -->
&lt;h3 id="why-ids-persist-during-incremental-runs">Why IDs persist during incremental runs&lt;/h3>&lt;p>The system carries forward the &lt;code>rudder_main_id&lt;/code> from the previous run via the previous mapping table. New nodes simply adopt the existing ID of the cluster they join.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="why-ids-persist-during-rebase-or-fresh-runs" data-heading="Why IDs persist during rebase or fresh runs" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/advanced-id-stitcher-features/advanced-operations/" data-title="Advanced ID Stitcher Operations" -->
&lt;h3 id="why-ids-persist-during-rebase-or-fresh-runs">Why IDs persist during rebase or fresh runs&lt;/h3>&lt;p>Even if you delete the previous mapping table, the anchor node for a specific user (for example, the first cookie they used in 2021) effectively remains the same in the raw data.&lt;/p>
&lt;ol>
&lt;li>The algorithm re-groups the cluster.&lt;/li>
&lt;li>It identifies the node with the minimum timestamp (the same 2021 cookie).&lt;/li>
&lt;li>It hashes that value.&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Result&lt;/strong>: The generated ID comes out identical to the previous run.&lt;/p>
&lt;br /></description></item></channel></rss>