<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RudderStack Docs – Incremental Features</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/</link><description>Recent content in Incremental 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/incremental-features/index.xml" rel="self" type="application/rss+xml"/><item><title>Archive: Simple Aggregations</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/</guid><description>
&lt;p>This guide explains simple aggregations and how to implement them as incremental features in Profiles.&lt;/p>
&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/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="overview">Overview&lt;/h2>&lt;p>Simple aggregations are direct composable aggregations that combine previous values with new data using straightforward merge functions.&lt;/p>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Only composable functions work&lt;/strong>: &lt;code>SUM&lt;/code>, &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, &lt;code>COUNT&lt;/code> are composable because results from different time periods can be merged correctly. &lt;code>AVG&lt;/code> is &lt;strong>NOT&lt;/strong> composable - you cannot average two averages correctly. For example, averaging 10 (from 5 values) and 20 (from 3 values) doesn&amp;rsquo;t give the correct overall average of 13.75. Use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a> for &lt;code>AVG&lt;/code>.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="motivation-when-and-why-to-use-simple-aggregations" data-heading="Motivation: When and why to use simple aggregations" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="motivation-when-and-why-to-use-simple-aggregations">Motivation: When and why to use simple aggregations&lt;/h2>&lt;p>Use simple aggregations when:&lt;/p>
&lt;ul>
&lt;li>You need to compute totals, counts, or min/max values&lt;/li>
&lt;li>Your aggregation uses composable functions: &lt;code>SUM&lt;/code>, &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, or &lt;code>COUNT&lt;/code>&lt;/li>
&lt;li>The merge operation is straightforward (sum previous + new, take min/max of previous and new)&lt;/li>
&lt;/ul>
&lt;p>Simple aggregations are the first pattern to try because they:&lt;/p>
&lt;ul>
&lt;li>Require minimal configuration (just add a &lt;code>merge:&lt;/code> clause)&lt;/li>
&lt;li>Have predictable behavior&lt;/li>
&lt;li>Are the most performant incremental pattern&lt;/li>
&lt;li>Work across all data warehouses&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 your use case doesn&amp;rsquo;t fit simple aggregations, consider &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a> or &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="real-world-examples" data-heading="Real-world examples" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="real-world-examples">Real-world examples&lt;/h2>&lt;p>Here are common use cases that map to simple aggregations:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Use case&lt;/th>
&lt;th>Aggregation&lt;/th>
&lt;th>Example&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Total lifetime value&lt;/strong>&lt;/td>
&lt;td>&lt;code>SUM&lt;/code>&lt;/td>
&lt;td>Sum of all purchases across a customer&amp;rsquo;s lifetime&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>First purchase date&lt;/strong>&lt;/td>
&lt;td>&lt;code>MIN&lt;/code>&lt;/td>
&lt;td>Earliest timestamp when a customer made their first purchase&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Last login time&lt;/strong>&lt;/td>
&lt;td>&lt;code>MAX&lt;/code>&lt;/td>
&lt;td>Most recent timestamp when a user logged in&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Total event count&lt;/strong>&lt;/td>
&lt;td>&lt;code>COUNT&lt;/code>&lt;/td>
&lt;td>Total number of events a user has generated&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="supported-simple-aggregators" data-heading="Supported simple aggregators" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="supported-simple-aggregators">Supported simple aggregators&lt;/h2>&lt;p>Profiles supports the following simple aggregators for incremental features:&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="sum" data-heading="SUM" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="sum">SUM&lt;/h3>&lt;p>Use &lt;code>SUM&lt;/code> for totals and cumulative values.&lt;/p>
&lt;p>&lt;strong>Example: Total lifetime value&lt;/strong>&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">entity_var&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">total_purchases&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{orders.value}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.total_purchases}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Total purchase value across all orders&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>: The &lt;code>merge&lt;/code> property adds the previous total to the new sum.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="min" data-heading="MIN" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="min">MIN&lt;/h3>&lt;p>Use &lt;code>MIN&lt;/code> for earliest values or minimum values.&lt;/p>
&lt;p>&lt;strong>Example: First purchase date&lt;/strong>&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">entity_var&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">first_purchase_date&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{orders.order_date}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{rowset.first_purchase_date}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">orders.status}} = &amp;#34;completed&amp;#34;&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Date of first completed purchase&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>: The &lt;code>merge&lt;/code> property takes the minimum of the previous and new values.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="max" data-heading="MAX" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="max">MAX&lt;/h3>&lt;p>Use &lt;code>MAX&lt;/code> for latest values or maximum values.&lt;/p>
&lt;p>&lt;strong>Example: Last login time&lt;/strong>&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">entity_var&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">last_purchase_date&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{orders.order_date}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.last_purchase_date}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Most recent purchase date&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>: The &lt;code>merge&lt;/code> property takes the maximum of the previous and new values.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="count" data-heading="COUNT" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="count">COUNT&lt;/h3>&lt;p>Use &lt;code>COUNT&lt;/code> for counting events or rows.&lt;/p>
&lt;p>&lt;strong>Example: Total event count&lt;/strong>&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">entity_var&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">event_count&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">COUNT(*)&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.event_count}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Total number of events&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">&lt;strong>Important&lt;/strong>: For &lt;code>COUNT&lt;/code> aggregations, always use &lt;code>SUM&lt;/code> in the &lt;code>merge&lt;/code> property, not &lt;code>COUNT&lt;/code>. You&amp;rsquo;re summing the counts from previous runs and new data, not counting counts.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;p>&lt;strong>How it works&lt;/strong>: The &lt;code>merge&lt;/code> property adds the previous count to the new count.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="merge-property-syntax" data-heading="&lt;code>merge&lt;/code> property syntax" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="merge-property-syntax">&lt;code>merge&lt;/code> property syntax&lt;/h2>&lt;p>The &lt;code>merge&lt;/code> property defines how to combine previous feature values (from the checkpoint) with new calculations.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="basic-syntax" data-heading="Basic syntax" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="basic-syntax">Basic syntax&lt;/h3>&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">entity_var&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">feature_name&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">AGGREGATION_FUNCTION(...)&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MERGE_FUNCTION({{rowset.feature_name}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/table_name&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="merge-function-reference" data-heading="Merge function reference" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="merge-function-reference">Merge function reference&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Select function&lt;/th>
&lt;th>Merge function&lt;/th>
&lt;th>Notes&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>MIN(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>MIN({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Takes minimum of previous and new values&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>MAX(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>MAX({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Takes maximum of previous and new values&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>SUM(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>SUM({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Sums previous and new values&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>COUNT(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>SUM({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Sums counts (not COUNT of counts)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="rowset-reference" data-heading="Rowset reference" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h3 id="rowset-reference">Rowset reference&lt;/h3>&lt;p>In &lt;code>merge&lt;/code> property, use &lt;code>{{rowset.feature_name}}&lt;/code> to reference one or more base aggregations from the baseline checkpoint, and the delta aggregation from current checkpoint.&lt;/p>
&lt;p>For example, if baseline &lt;code>ID1&lt;/code>, &lt;code>ID2&lt;/code> and &lt;code>ID3&lt;/code> merge into current checkpoint &lt;code>ID2&lt;/code>, then you would be merging the following rowsets:&lt;/p>
&lt;ol>
&lt;li>All input rows associated with &lt;code>ID1&lt;/code> and part of baseline.&lt;/li>
&lt;li>All input rows associated with &lt;code>ID2&lt;/code> and part of baseline.&lt;/li>
&lt;li>All input rows associated with &lt;code>ID3&lt;/code> and part of baseline.&lt;/li>
&lt;li>All input rows landing between baseline and current checkpoint, and mapped to the merged &lt;code>ID2&lt;/code>.&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Key points&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;code>{{rowset.feature_name}}&lt;/code>: References the previous value of &lt;code>feature_name&lt;/code> from the checkpoint&lt;/li>
&lt;li>&lt;code>{{rowset.column_name}}&lt;/code>: References any column from the previous checkpoint&lt;/li>
&lt;li>&lt;code>{{this.feature_name}}&lt;/code>: References the new value being computed (used in &lt;code>merge_where&lt;/code> clauses)&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="when-simple-aggregations-dont-work" data-heading="When simple aggregations don&amp;rsquo;t work" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="when-simple-aggregations-dont-work">When simple aggregations don&amp;rsquo;t work&lt;/h2>&lt;p>Simple aggregations may not be sufficient when:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Your aggregation isn&amp;rsquo;t directly composable&lt;/strong>: &lt;code>AVG&lt;/code>(&lt;code>WEIGHTED_AVG&lt;/code>) cannot be computed directly. Use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a> and combine helper aggregations like &lt;code>SUM(weighted sum)&lt;/code> and &lt;code>COUNT(sum_of_weights)&lt;/code>.&lt;/li>
&lt;li>&lt;strong>You need MIN_BY/MAX_BY aggregations&lt;/strong>: Selecting a value based on the min/max of another column (for example, &lt;code>LAST_KNOWN_LOCATION&lt;/code> using &lt;code>MAX_BY(location, timestamp)&lt;/code> or &lt;code>FIRST_PURCHASE_STORE&lt;/code> using &lt;code>MIN_BY(store, purchase_date)&lt;/code>) requires a &lt;code>_by_param&lt;/code> helper var. See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/#min_by--max_by-with-ordering-helper" >MIN_BY/MAX_BY with ordering helper&lt;/a>.&lt;/li>
&lt;li>&lt;strong>You need to replace window functions&lt;/strong>: &lt;code>LAST_VALUE&lt;/code>, &lt;code>FIRST_VALUE&lt;/code>, and other window functions are not composable — replace them with &lt;code>MAX_BY&lt;/code>/&lt;code>MIN_BY&lt;/code>. See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/#replace-window-functions" >Replace window functions&lt;/a>.&lt;/li>
&lt;li>&lt;strong>You need array aggregations&lt;/strong>: Lists and arrays require union operations. Use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>.&lt;/li>
&lt;li>&lt;strong>You need time window aggregations&lt;/strong>: When you need to aggregate running totals, balances including or multi-step aggregations within a time window, you can create an incremental input window using &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>.&lt;/li>
&lt;li>&lt;strong>You need PIVOT operations&lt;/strong>: When you need to transform rows into columns (for example, &lt;code>last_login_by_device_id&lt;/code> to track the last login time for each device separately). You can use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a> to achieve this.&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="merge_where-for-conditional-merging" data-heading="&lt;code>merge_where&lt;/code> for conditional merging" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="merge_where-for-conditional-merging">&lt;code>merge_where&lt;/code> for conditional merging&lt;/h2>&lt;p>You can use the &lt;code>merge_where:&lt;/code> clause to restrict merging to only those &lt;strong>rowsets&lt;/strong> that meet specific conditions:&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">entity_var&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">timestamp&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{game_events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.timestamp}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/game_events&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">game_events.event_type}} = &amp;#34;BREAK&amp;#34;&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Timestamp of the most recent break event (used for score lookup)&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">entity_var&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">score_at_last_break&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">any_value({{game_events.score}})&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">game_events.timestamp}} = {{user.timestamp}}&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">any_value({{game_events.score}})&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">merge_where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">rowset.timestamp}} = {{user.timestamp}}&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/game_events&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Score at the most recent break event&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Use &lt;code>{{rowset.column}}&lt;/code> for previous values and &lt;code>{{this.column}}&lt;/code> for new values in the condition.&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/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="best-practices">Best practices&lt;/h2>&lt;ul>
&lt;li>Start with simple aggregations before moving to more complex patterns&lt;/li>
&lt;li>Ensure &lt;code>merge&lt;/code> property matches the aggregation function&lt;/li>
&lt;li>For &lt;code>COUNT&lt;/code>, always use &lt;code>SUM&lt;/code> in the &lt;code>merge&lt;/code> property&lt;/li>
&lt;li>Use &lt;code>merge_where:&lt;/code> only when you need conditional merging logic&lt;/li>
&lt;li>Verify incremental results match full refresh results&lt;/li>
&lt;/ul>
&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/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Issue&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>merge&lt;/code> function does not match aggregation type&lt;/td>
&lt;td>Ensure &lt;code>merge&lt;/code> function matches select aggregation (&lt;code>SUM&lt;/code> for &lt;code>SUM&lt;/code>, &lt;code>MIN&lt;/code> for &lt;code>MIN&lt;/code>, etc.)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Missing rowset reference&lt;/td>
&lt;td>Use &lt;code>{{rowset.feature_name}}&lt;/code> to reference previous values from checkpoint&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>COUNT&lt;/code> merge using &lt;code>COUNT&lt;/code> instead of &lt;code>SUM&lt;/code>&lt;/td>
&lt;td>Use &lt;code>SUM({{rowset.feature_name}})&lt;/code> for COUNT aggregations&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Incorrect merge results&lt;/td>
&lt;td>Verify &lt;code>merge_where:&lt;/code> conditions are logically correct, if used&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="see-more" data-heading="See more" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" data-title="Simple Aggregations" -->
&lt;h2 id="see-more">See more&lt;/h2>&lt;ul>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" >How to Make Features Incremental&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/profiles-yaml/var-groups/entity-var/" >Entity Vars&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Archive: Compound Aggregations</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/</guid><description>
&lt;p>This guide explains compound aggregations and how to implement them as incremental features in Profiles.&lt;/p>
&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/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="overview">Overview&lt;/h2>&lt;p>Compound aggregations require intermediate calculations or multiple steps, each implemented as a simple composable aggregation. They break complex aggregations into component parts that can be maintained incrementally.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="motivation-when-and-why-to-use-compound-aggregations" data-heading="Motivation: When and why to use compound aggregations" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="motivation-when-and-why-to-use-compound-aggregations">Motivation: When and why to use compound aggregations&lt;/h2>&lt;p>Use compound aggregations when:&lt;/p>
&lt;ul>
&lt;li>You need to compute averages (&lt;code>AVG&lt;/code>, &lt;code>WEIGHTED_AVG&lt;/code>), which cannot be computed directly incrementally&lt;/li>
&lt;li>You need to select values based on min/max of another column (&lt;code>MIN_BY&lt;/code>, &lt;code>MAX_BY&lt;/code>)&lt;/li>
&lt;li>You need to &lt;a href="#replace-window-functions" >replace window functions&lt;/a> (&lt;code>LAST_VALUE&lt;/code>, &lt;code>FIRST_VALUE&lt;/code>) with incremental alternatives&lt;/li>
&lt;li>You need to aggregate arrays or lists that require union and sorting operations&lt;/li>
&lt;li>You need boolean aggregations (&lt;code>BOOLOR_AGG&lt;/code>, &lt;code>BOOLAND_AGG&lt;/code>)&lt;/li>
&lt;li>Your aggregation requires multiple intermediate calculations&lt;/li>
&lt;/ul>
&lt;p>Compound aggregations use:&lt;/p>
&lt;ul>
&lt;li>Component parts (like sum and count for averages)&lt;/li>
&lt;li>Intermediate entity vars maintained incrementally&lt;/li>
&lt;li>Final calculations that combine components&lt;/li>
&lt;/ul>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Tip:&lt;/strong>
If compound aggregations don&amp;rsquo;t fit your use case, consider &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a> for stateful processing or complex transformations.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="real-world-examples" data-heading="Real-world examples" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="real-world-examples">Real-world examples&lt;/h2>&lt;p>Here are common use cases that map to compound aggregations:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Use case&lt;/th>
&lt;th>Pattern&lt;/th>
&lt;th>Example&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Average order value&lt;/strong>&lt;/td>
&lt;td>AVG using sum/count&lt;/td>
&lt;td>Average purchase amount across all orders&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Average session duration&lt;/strong>&lt;/td>
&lt;td>AVG using sum/count&lt;/td>
&lt;td>Average time spent per session&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Weighted average rating&lt;/strong>&lt;/td>
&lt;td>WEIGHTED_AVG using weighted sum/weight sum&lt;/td>
&lt;td>Average product rating weighted by number of reviews&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>List of countries visited&lt;/strong>&lt;/td>
&lt;td>Array aggregation&lt;/td>
&lt;td>Sorted list of unique countries a user has visited&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Array of product IDs&lt;/strong>&lt;/td>
&lt;td>Array aggregation&lt;/td>
&lt;td>List of all product IDs a user has purchased&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Most recent login platform&lt;/strong>&lt;/td>
&lt;td>MIN_BY/MAX_BY with helper&lt;/td>
&lt;td>Platform of the most recent login event&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>First campaign source&lt;/strong>&lt;/td>
&lt;td>MIN_BY/MAX_BY with helper&lt;/td>
&lt;td>Campaign source from the earliest identification&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Has ever enabled push&lt;/strong>&lt;/td>
&lt;td>Boolean aggregation&lt;/td>
&lt;td>Whether a user has ever enabled push notifications&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="average-avg-using-component-features" data-heading="Average (AVG) using component features" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="average-avg-using-component-features">Average (AVG) using component features&lt;/h2>&lt;p>&lt;code>AVG&lt;/code> cannot be computed directly incrementally. Express it using sum and count components:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Sum component&lt;/strong>: Maintain sum incrementally using &lt;code>SUM&lt;/code> with &lt;code>SUM&lt;/code> merge&lt;/li>
&lt;li>&lt;strong>Count component&lt;/strong>: Maintain count incrementally using &lt;code>COUNT&lt;/code> with &lt;code>SUM&lt;/code> merge (counts from previous checkpoints are summed together)&lt;/li>
&lt;li>&lt;strong>Average calculation&lt;/strong>: Divide sum by count in a final entity var with division by zero protection&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-average-order-value" data-heading="Example: Average order value" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-average-order-value">Example: Average order value&lt;/h3>&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">entity_var&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">sum_of_order_values&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{orders.amount}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.sum_of_order_values}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sum of order values (used for average calculation)&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">entity_var&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">count_of_orders&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">COUNT({{orders.order_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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.count_of_orders}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Count of orders (used for average calculation)&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">entity_var&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">avg_order_value&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;CASE WHEN {{user.count_of_orders}} &amp;gt; 0 THEN {{user.sum_of_order_values}} / {{user.count_of_orders}} ELSE 0 END&amp;#34;&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Average order value across all orders&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Sum component&lt;/strong>: Maintains total sum incrementally using &lt;code>SUM&lt;/code> with &lt;code>SUM&lt;/code> merge&lt;/li>
&lt;li>&lt;strong>Count component&lt;/strong>: Maintains total count incrementally using &lt;code>COUNT&lt;/code> with &lt;code>SUM&lt;/code> merge (counts from previous checkpoints are summed together)&lt;/li>
&lt;li>&lt;strong>Average calculation&lt;/strong>: Divides sum by count using &lt;code>{{user.var_name}}&lt;/code> syntax, with division by zero protection&lt;/li>
&lt;/ol>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Tip:&lt;/strong>
Mark sum and count components with &lt;code>is_feature: false&lt;/code> since they&amp;rsquo;re intermediate calculations. The average is computed on-the-fly from the incrementally maintained components.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="workflow" data-heading="Workflow" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="workflow">Workflow&lt;/h3>&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">Input Data → [Sum Component (Incremental)] → Final Calculation
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → [Count Component (Incremental)] ↗
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>Profiles creates intermediate tables for sum and count components&lt;/li>
&lt;li>Both components are maintained incrementally using simple aggregation patterns&lt;/li>
&lt;li>The average is computed by dividing sum by count (with division by zero protection)&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="weighted-average-weighted_avg-using-component-features" data-heading="Weighted Average (WEIGHTED_AVG) using component features" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="weighted-average-weighted_avg-using-component-features">Weighted Average (WEIGHTED_AVG) using component features&lt;/h2>&lt;p>&lt;code>WEIGHTED_AVG&lt;/code> cannot be computed directly incrementally. You can express it using weighted sum and sum of weights components:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Weighted sum component&lt;/strong>: Maintain sum of (value × weight) incrementally using &lt;code>SUM&lt;/code> with &lt;code>SUM&lt;/code> merge&lt;/li>
&lt;li>&lt;strong>Sum of weights component&lt;/strong>: Maintain sum of weights incrementally using &lt;code>SUM&lt;/code> with &lt;code>SUM&lt;/code> merge&lt;/li>
&lt;li>&lt;strong>Weighted average calculation&lt;/strong>: Divide weighted sum by sum of weights in a final entity var with division by zero protection&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-weighted-average-product-rating" data-heading="Example: Weighted average product rating" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-weighted-average-product-rating">Example: Weighted average product rating&lt;/h3>&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">entity_var&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">weighted_sum_of_ratings&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{reviews.rating}} * {{reviews.review_count}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.weighted_sum_of_ratings}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/reviews&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sum of (rating × review_count) for weighted average calculation&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">entity_var&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">sum_of_review_counts&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{reviews.review_count}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.sum_of_review_counts}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/reviews&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sum of review counts (weights) for weighted average calculation&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">entity_var&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">weighted_avg_rating&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;CASE WHEN {{user.sum_of_review_counts}} &amp;gt; 0 THEN {{user.weighted_sum_of_ratings}} / {{user.sum_of_review_counts}} ELSE 0 END&amp;#34;&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Weighted average product rating across all reviews&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Weighted sum component&lt;/strong>: Maintains sum of (value × weight) incrementally using &lt;code>SUM&lt;/code> with &lt;code>SUM&lt;/code> merge
-&lt;strong>Sum of weights component&lt;/strong>: Maintains total sum of weights incrementally using &lt;code>SUM&lt;/code> with &lt;code>SUM&lt;/code> merge&lt;/li>
&lt;li>&lt;strong>Weighted average calculation&lt;/strong>: Divides weighted sum by sum of weights using &lt;code>{{user.var_name}}&lt;/code> syntax, with division by zero protection&lt;/li>
&lt;/ul>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Tip:&lt;/strong>
Mark weighted sum and sum of weights components with &lt;code>is_feature: false&lt;/code> since they&amp;rsquo;re intermediate calculations. The weighted average is computed on-the-fly from the incrementally maintained components.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="workflow-1" data-heading="Workflow" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="workflow-1">Workflow&lt;/h3>&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">Input Data → [Weighted Sum Component (Incremental)] → Final Calculation
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> → [Sum of Weights Component (Incremental)] ↗
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>Profiles creates intermediate tables for weighted sum and sum of weights components&lt;/li>
&lt;li>Both components are maintained incrementally using simple aggregation patterns&lt;/li>
&lt;li>The weighted average is computed by dividing weighted sum by sum of weights (with division by zero protection)&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="array-aggregations" data-heading="Array aggregations" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="array-aggregations">Array aggregations&lt;/h2>&lt;p>For array aggregations, use &lt;code>ARRAY_UNION_AGG&lt;/code> or &lt;code>ARRAY_SORT&lt;/code> in the &lt;code>merge&lt;/code> property to combine arrays from previous checkpoints with new arrays.&lt;/p>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Warehouse-specific syntax&lt;/strong>: Array aggregation syntax varies by warehouse. The examples in this section are specific to Snowflake. Adjust syntax for your warehouse.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-list-of-countries-visited" data-heading="Example: List of countries visited" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-list-of-countries-visited">Example: List of countries visited&lt;/h3>&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">entity_var&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">countries_list&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ARRAY_AGG(DISTINCT {{tracks.country}}) WITHIN GROUP (ORDER BY {{tracks.country}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ARRAY_SORT(ARRAY_UNION_AGG({{rowset.countries_list}}))&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/tracks&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">country IS NOT NULL&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sorted list of unique countries&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Select clause&lt;/strong>: Creates an array of distinct countries from new data, sorted&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Merge property&lt;/strong>:&lt;/p>
&lt;ul>
&lt;li>&lt;code>ARRAY_UNION_AGG({{rowset.countries_list}})&lt;/code>: Unions previous and new arrays, removing duplicates&lt;/li>
&lt;li>&lt;code>ARRAY_SORT(...)&lt;/code>: Sorts the final array&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="array-merge-functions" data-heading="Array merge functions" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="array-merge-functions">Array merge functions&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Select function&lt;/th>
&lt;th>Merge function&lt;/th>
&lt;th>Notes&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>ARRAY_AGG(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>ARRAY_UNION_AGG({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Unions arrays, removing duplicates&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ARRAY_AGG(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>ARRAY_SORT(ARRAY_UNION_AGG({{rowset.feature_name}}))&lt;/code>&lt;/td>
&lt;td>Unions and sorts arrays&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="min_by--max_by-with-ordering-helper" data-heading="MIN_BY / MAX_BY with ordering helper" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="min_by--max_by-with-ordering-helper">MIN_BY / MAX_BY with ordering helper&lt;/h2>&lt;p>&lt;code>MIN_BY&lt;/code> and &lt;code>MAX_BY&lt;/code> select a value from the row with the minimum or maximum of another column. These are common replacements for window functions like &lt;code>FIRST_VALUE&lt;/code> and &lt;code>LAST_VALUE&lt;/code>.&lt;/p>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>Required: &lt;code>_by_param&lt;/code> helper var.&lt;/strong>&lt;/p>
&lt;p>When using &lt;code>MIN_BY&lt;/code> or &lt;code>MAX_BY&lt;/code> in a &lt;code>merge&lt;/code> clause, you &lt;strong>must&lt;/strong> define a companion entity var (conventionally suffixed &lt;code>_by_param&lt;/code>) that tracks the ordering column. Omitting this helper breaks incremental runs because the merge has no ordering context from previous checkpoints.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-most-recent-login-platform" data-heading="Example: Most recent login platform" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-most-recent-login-platform">Example: Most recent login platform&lt;/h3>&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">entity_var&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">last_login_platform&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{logins.platform}}, {{logins.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{rowset.last_login_platform}}, {{rowset.last_login_platform_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/logins&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Platform of the most recent login&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">entity_var&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">last_login_platform_by_param&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{logins.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.last_login_platform_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/logins&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Ordering helper for last_login_platform&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Main var&lt;/strong>: &lt;code>MAX_BY(platform, timestamp)&lt;/code> selects the platform from the row with the latest timestamp&lt;/li>
&lt;li>&lt;strong>Helper var&lt;/strong>: &lt;code>MAX(timestamp)&lt;/code> tracks the latest timestamp across checkpoints&lt;/li>
&lt;li>&lt;strong>Merge&lt;/strong>: &lt;code>MAX_BY({{rowset.last_login_platform}}, {{rowset.last_login_platform_by_param}})&lt;/code> compares the previous value&amp;rsquo;s timestamp with the new value&amp;rsquo;s timestamp and keeps the one with the later timestamp&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-first-purchase-store" data-heading="Example: First purchase store" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-first-purchase-store">Example: First purchase store&lt;/h3>&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">entity_var&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">first_purchase_store&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN_BY({{orders.store_name}}, {{orders.order_date}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN_BY({{rowset.first_purchase_store}}, {{rowset.first_purchase_store_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Store where the user made their first purchase&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">entity_var&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">first_purchase_store_by_param&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{orders.order_date}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{rowset.first_purchase_store_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Ordering helper for first_purchase_store&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="min_by--max_by-merge-reference" data-heading="MIN_BY / MAX_BY merge reference" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="min_by--max_by-merge-reference">MIN_BY / MAX_BY merge reference&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Select function&lt;/th>
&lt;th>Merge function&lt;/th>
&lt;th>Helper var&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>MIN_BY(value_col, order_col)&lt;/code>&lt;/td>
&lt;td>&lt;code>MIN_BY({{rowset.feature}}, {{rowset.feature_by_param}})&lt;/code>&lt;/td>
&lt;td>&lt;code>MIN(order_col)&lt;/code> with &lt;code>MIN&lt;/code> merge&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>MAX_BY(value_col, order_col)&lt;/code>&lt;/td>
&lt;td>&lt;code>MAX_BY({{rowset.feature}}, {{rowset.feature_by_param}})&lt;/code>&lt;/td>
&lt;td>&lt;code>MAX(order_col)&lt;/code> with &lt;code>MAX&lt;/code> merge&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="when-you-can-skip-the-_by_param-helper" data-heading="When you can skip the &lt;code>_by_param&lt;/code> helper" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="when-you-can-skip-the-_by_param-helper">When you can skip the &lt;code>_by_param&lt;/code> helper&lt;/h3>&lt;p>You can skip the helper only when the ordering column is irrelevant to the merge. For example, when you always want the latest value and don&amp;rsquo;t need to track when it changed. In practice, this is rare — however when in doubt, include the helper.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="boolean-aggregations" data-heading="Boolean aggregations" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="boolean-aggregations">Boolean aggregations&lt;/h2>&lt;p>For boolean OR aggregations, use &lt;code>BOOLOR_AGG&lt;/code> in both &lt;code>select&lt;/code> and &lt;code>merge&lt;/code>:&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-has-user-ever-enabled-push-notifications" data-heading="Example: Has user ever enabled push notifications" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-has-user-ever-enabled-push-notifications">Example: Has user ever enabled push notifications&lt;/h3>&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">entity_var&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">has_ever_enabled_push&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">BOOLOR_AGG(COALESCE({{settings.push_enabled}}, 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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">BOOLOR_AGG({{rowset.has_ever_enabled_push}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/settings&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Whether the user has ever enabled push notifications&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>How it works&lt;/strong>: &lt;code>BOOLOR_AGG&lt;/code> returns &lt;code>true&lt;/code> if any value in the group is &lt;code>true&lt;/code>. Since boolean OR is composable (once &lt;code>true&lt;/code>, always &lt;code>true&lt;/code>), previous and new results can be merged directly.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="boolean-merge-reference" data-heading="Boolean merge reference" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="boolean-merge-reference">Boolean merge reference&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Select function&lt;/th>
&lt;th>Merge function&lt;/th>
&lt;th>Notes&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>BOOLOR_AGG(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>BOOLOR_AGG({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Boolean OR: true if any value is true&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>BOOLAND_AGG(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>BOOLAND_AGG({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;td>Boolean AND: true only if all values are true&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>Warehouse-specific syntax&lt;/strong>: &lt;code>BOOLOR_AGG&lt;/code> and &lt;code>BOOLAND_AGG&lt;/code> are Snowflake functions.&lt;/p>
&lt;p>For other warehouses, use equivalent functions (for example, &lt;code>LOGICAL_OR&lt;/code> / &lt;code>LOGICAL_AND&lt;/code> in BigQuery, &lt;code>BOOL_OR&lt;/code> / &lt;code>BOOL_AND&lt;/code> in Redshift and Databricks).&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="replace-window-functions" data-heading="Replace window functions" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="replace-window-functions">Replace window functions&lt;/h2>&lt;p>Window functions like &lt;code>LAST_VALUE&lt;/code>, &lt;code>FIRST_VALUE&lt;/code>, &lt;code>LAG&lt;/code>, and &lt;code>LEAD&lt;/code> cannot be used in incremental entity vars because they require scanning all data to determine row ordering. Replace them with composable alternatives.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="common-replacements" data-heading="Common replacements" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="common-replacements">Common replacements&lt;/h3>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Window function&lt;/th>
&lt;th>Incremental replacement&lt;/th>
&lt;th>Pattern&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>LAST_VALUE(col) OVER (ORDER BY ts)&lt;/code>&lt;/td>
&lt;td>&lt;code>MAX_BY(col, ts)&lt;/code>&lt;/td>
&lt;td>&lt;a href="#min_by--max_by-with-ordering-helper" >MIN_BY/MAX_BY with helper&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>FIRST_VALUE(col) OVER (ORDER BY ts)&lt;/code>&lt;/td>
&lt;td>&lt;code>MIN_BY(col, ts)&lt;/code>&lt;/td>
&lt;td>&lt;a href="#min_by--max_by-with-ordering-helper" >MIN_BY/MAX_BY with helper&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ROW_NUMBER()&lt;/code>, &lt;code>RANK()&lt;/code>, &lt;code>DENSE_RANK()&lt;/code>&lt;/td>
&lt;td>Not directly replaceable&lt;/td>
&lt;td>Use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>LAG()&lt;/code>, &lt;code>LEAD()&lt;/code>&lt;/td>
&lt;td>Not directly replaceable&lt;/td>
&lt;td>Use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-replace-last_value-with-max_by" data-heading="Example: Replace LAST_VALUE with MAX_BY" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-replace-last_value-with-max_by">Example: Replace LAST_VALUE with MAX_BY&lt;/h3>&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 (non-incremental, uses window function)&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">entity_var&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">last_known_city&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">last_value(city)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">window&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">order_by&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">timestamp&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">city IS NOT NULL&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 (incremental, uses MAX_BY with helper)&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">entity_var&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">last_known_city&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{events.city}}, {{events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{rowset.last_known_city}}, {{rowset.last_known_city_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">events.city}} IS NOT NULL&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Most recent city from events&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">entity_var&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">last_known_city_by_param&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.last_known_city_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">events.city}} IS NOT NULL&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Ordering helper for last_known_city&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-replace-first_value-with-min_by" data-heading="Example: Replace FIRST_VALUE with MIN_BY" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h3 id="example-replace-first_value-with-min_by">Example: Replace FIRST_VALUE with MIN_BY&lt;/h3>&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 (non-incremental, uses window function)&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">entity_var&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">first_campaign_source&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">first_value(campaign_source)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/identifies&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">window&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">order_by&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">timestamp&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">campaign_source IS NOT NULL&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 (incremental, uses MIN_BY with helper)&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">entity_var&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">first_campaign_source&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN_BY({{identifies.campaign_source}}, {{identifies.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN_BY({{rowset.first_campaign_source}}, {{rowset.first_campaign_source_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/identifies&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">identifies.campaign_source}} IS NOT NULL&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Campaign source from first identification&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">entity_var&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">first_campaign_source_by_param&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{identifies.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{rowset.first_campaign_source_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/identifies&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">identifies.campaign_source}} IS NOT NULL&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Ordering helper for first_campaign_source&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="when-compound-aggregations-dont-work" data-heading="When compound aggregations don&amp;rsquo;t work" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="when-compound-aggregations-dont-work">When compound aggregations don&amp;rsquo;t work&lt;/h2>&lt;p>Compound aggregations may not be sufficient when:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>You need activity windows&lt;/strong>: Tracking recent activity over time windows (like MAU/DAU) requires &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models with Incremental Input Windows&lt;/a>.&lt;/li>
&lt;li>&lt;strong>You need per-object aggregations&lt;/strong>: Instead of one value per user, you need one value per (user_id, object_id) pair, where object_id could be product_id, location_id, or any other dimension. This requires &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>.&lt;/li>
&lt;li>&lt;strong>You need complex business logic&lt;/strong>: Multi-step transformations with conditional logic may require &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>.&lt;/li>
&lt;/ul>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>Input-vars cannot be built incrementally&lt;/strong>&lt;/p>
&lt;p>An &lt;code>entity_var&lt;/code> dependent on an &lt;code>input_var&lt;/code> cannot be incremental. To enable incremental features, replace the &lt;code>input_var&lt;/code> with an &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Model&lt;/a> and reference the model from the &lt;code>entity_var&lt;/code> instead.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&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/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="best-practices">Best practices&lt;/h2>&lt;ul>
&lt;li>Break &lt;code>AVG&lt;/code> into sum and count components with separate &lt;code>merge&lt;/code> properties&lt;/li>
&lt;li>Break &lt;code>WEIGHTED_AVG&lt;/code> into weighted sum (value × weight) and sum of weights components with separate &lt;code>merge&lt;/code> properties&lt;/li>
&lt;li>Always define a &lt;code>_by_param&lt;/code> helper var when using &lt;code>MIN_BY&lt;/code>/&lt;code>MAX_BY&lt;/code> in merge clauses&lt;/li>
&lt;li>Replace &lt;code>LAST_VALUE&lt;/code> window functions with &lt;code>MAX_BY&lt;/code>, and &lt;code>FIRST_VALUE&lt;/code> with &lt;code>MIN_BY&lt;/code>&lt;/li>
&lt;li>Mark intermediate entity vars (helpers, components) with &lt;code>is_feature: false&lt;/code> to avoid exposing them as features&lt;/li>
&lt;li>Add division by zero protection when computing averages (use &lt;code>CASE WHEN count &amp;gt; 0 THEN sum/count ELSE 0 END&lt;/code> for AVG, or &lt;code>CASE WHEN sum_of_weights &amp;gt; 0 THEN weighted_sum / sum_of_weights ELSE 0 END&lt;/code> for WEIGHTED_AVG)&lt;/li>
&lt;li>Use &lt;code>ARRAY_UNION_AGG&lt;/code> for array aggregations to maintain deduplication&lt;/li>
&lt;li>Be aware of warehouse-specific syntax differences for array and boolean operations&lt;/li>
&lt;li>Verify incremental results match full refresh results&lt;/li>
&lt;/ul>
&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/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Issue&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Average calculation returns incorrect values&lt;/td>
&lt;td>Verify that sum and count components are correctly maintained incrementally and include division by zero protection&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Weighted average calculation returns incorrect values&lt;/td>
&lt;td>Verify that weighted sum (value × weight) and sum of weights components are correctly maintained incrementally and include division by zero protection&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Division by zero errors&lt;/td>
&lt;td>Add &lt;code>CASE WHEN count &amp;gt; 0 THEN sum/count ELSE 0 END&lt;/code> for AVG, or &lt;code>CASE WHEN sum_of_weights &amp;gt; 0 THEN weighted_sum / sum_of_weights ELSE 0 END&lt;/code> for WEIGHTED_AVG&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Array aggregation syntax errors&lt;/td>
&lt;td>Check warehouse-specific syntax requirements (Snowflake, BigQuery, etc.)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Duplicate values in arrays&lt;/td>
&lt;td>Ensure &lt;code>ARRAY_UNION_AGG&lt;/code> is used in &lt;code>merge&lt;/code> property to remove duplicates&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Intermediate features appearing in output&lt;/td>
&lt;td>Mark intermediate entity vars with &lt;code>is_feature: false&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Missing &lt;code>_by_param&lt;/code> helper for MIN_BY/MAX_BY&lt;/td>
&lt;td>Define a companion entity var (suffixed &lt;code>_by_param&lt;/code>) that tracks the ordering column with &lt;code>is_feature: false&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MIN_BY/MAX_BY merge returns wrong value&lt;/td>
&lt;td>Verify the &lt;code>_by_param&lt;/code> helper uses the same &lt;code>from&lt;/code>, &lt;code>where&lt;/code>, and ordering column as the main var&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Boolean aggregation syntax errors&lt;/td>
&lt;td>Use warehouse-appropriate function: &lt;code>BOOLOR_AGG&lt;/code> (Snowflake), &lt;code>LOGICAL_OR&lt;/code> (BigQuery), &lt;code>BOOL_OR&lt;/code> (Redshift/Databricks)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="see-more" data-heading="See more" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" data-title="Compound Aggregations" -->
&lt;h2 id="see-more">See more&lt;/h2>&lt;ul>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" >How to Make Features Incremental&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/profiles-yaml/var-groups/entity-var/" >Entity Vars&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Archive: Incremental SQL Models</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/</guid><description>
&lt;p>This guide explains incremental SQL models and how they enable complex stateful processing in Profiles.&lt;/p>
&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/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="overview">Overview&lt;/h2>&lt;p>Incremental SQL models are &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/sql-models/" >SQL models&lt;/a> that dereference their own previous materialization to enable incremental processing. They enable complex patterns requiring stateful processing, running totals, or multi-step transformations that cannot be expressed using simple incremental entity vars.&lt;/p>
&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/incremental-sql-models/" >Incremental SQL Models Overview&lt;/a> for conceptual information.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="what-are-incremental-sql-models" data-heading="What are incremental SQL models?" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="what-are-incremental-sql-models">What are incremental SQL models?&lt;/h2>&lt;p>An incremental SQL model is a SQL-template model that:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Dereferences a previous materialization of itself using &lt;code>this.DeRef()&lt;/code> with &lt;code>pre_existing=true&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Produces the same final result whether the previous state is available or not (idempotence)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Operates with two checkpoints:&lt;/p>
&lt;ul>
&lt;li>Current checkpoint: The checkpoint being produced now&lt;/li>
&lt;li>Baseline checkpoint: A previous checkpoint represented by the previous materialization&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>When the previous state is present, the model merges its prior state with new/changed inputs; otherwise it runs a full scan.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="when-and-why-to-use-incremental-sql-models" data-heading="When and why to use incremental SQL models" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="when-and-why-to-use-incremental-sql-models">When and why to use incremental SQL models&lt;/h2>&lt;p>Use incremental SQL models when:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Simple aggregations don&amp;rsquo;t work&lt;/strong>: Your use case requires stateful processing that cannot be expressed with &lt;code>SUM&lt;/code>, &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, or &lt;code>COUNT&lt;/code> in your &lt;code>merge&lt;/code> property&lt;/li>
&lt;li>&lt;strong>Compound aggregations don&amp;rsquo;t work&lt;/strong>: Your use case requires complex transformations beyond averages or arrays&lt;/li>
&lt;li>&lt;strong>You need activity windows&lt;/strong>: Tracking recent activity over time windows (like MAU/DAU)&lt;/li>
&lt;li>&lt;strong>You need window functions or composite key aggregations&lt;/strong>: Per-dimension aggregations or window-based calculations&lt;/li>
&lt;li>&lt;strong>You need multi-step transformations&lt;/strong>: Complex business logic that requires multiple steps or conditional processing&lt;/li>
&lt;/ul>
&lt;p>Incremental SQL models let you:&lt;/p>
&lt;ul>
&lt;li>Reference previous computation results using &lt;code>this.DeRef()&lt;/code>&lt;/li>
&lt;li>Maintain stateful aggregations across runs&lt;/li>
&lt;li>Implement complex business logic with full SQL control&lt;/li>
&lt;li>Handle both incremental and full refresh modes&lt;/li>
&lt;/ul>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>Tip:&lt;/strong>
For simple aggregations like &lt;code>SUM&lt;/code>, &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, &lt;code>COUNT&lt;/code>, prefer using &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a> with &lt;code>merge&lt;/code> property. For averages and arrays, use &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>.&lt;/p>
&lt;p>Incremental SQL models are best for complex scenarios.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="real-world-examples" data-heading="Real-world examples" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="real-world-examples">Real-world examples&lt;/h2>&lt;p>Some common use cases that map to incremental SQL models are listed below:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Use case&lt;/th>
&lt;th>Pattern&lt;/th>
&lt;th>Example&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Monthly Active Users (MAU)&lt;/strong>&lt;/td>
&lt;td>Incremental Input Window Models&lt;/td>
&lt;td>Count of users active in the past 30 days&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Daily Active Users (DAU)&lt;/strong>&lt;/td>
&lt;td>Incremental Input Window Models&lt;/td>
&lt;td>Count of users active today&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Account balances by wallet&lt;/strong>&lt;/td>
&lt;td>Composite Key Models&lt;/td>
&lt;td>Account balance per (user_id, wallet_id) composite key maintained across transactions - each user has multiple wallets with individual balances&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Recent activity tracking&lt;/strong>&lt;/td>
&lt;td>Incremental Input Window Models&lt;/td>
&lt;td>Tracking recent interactions within a time window&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="incremental-sql-models-subcategories" data-heading="Incremental SQL models subcategories" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="incremental-sql-models-subcategories">Incremental SQL models subcategories&lt;/h2>&lt;p>Incremental SQL models can be categorized into two main patterns:&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="incremental-input-window-models" data-heading="Incremental input window models" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="incremental-input-window-models">Incremental input window models&lt;/h3>&lt;p>&lt;strong>When to use&lt;/strong>: Tracking recent activity or maintaining rolling windows of data.&lt;/p>
&lt;p>&lt;strong>Characteristics&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Maintain a rolling window of recent interactions (e.g., last 90 days of activity)&lt;/li>
&lt;li>Track activity over time windows (MAU, DAU, weekly active users)&lt;/li>
&lt;li>Filter and maintain only recent data incrementally&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Example&lt;/strong>: Monthly Active Users (MAU) or Daily Active Users (DAU) where you need to track which users were active in a recent time window.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="composite-key-models" data-heading="Composite key models" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="composite-key-models">Composite key models&lt;/h3>&lt;p>&lt;strong>When to use&lt;/strong>: Per-dimension aggregations where you need one value per (entity_id, dimension_id) composite key pair.&lt;/p>
&lt;p>&lt;strong>Characteristics&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Maintain aggregations per (entity_id, dimension_id) composite key instead of just per entity_id&lt;/li>
&lt;li>Handle multi-dimensional state with composite key granularity&lt;/li>
&lt;li>Support complex logic where each entity has multiple related objects to track&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Example&lt;/strong>: Account balances by wallet where each user (entity_id) has multiple wallets (dimension_id), and you need to maintain a separate balance for each wallet. This is a composite key pattern common in financial applications.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="how-incremental-sql-models-work" data-heading="How incremental SQL models work" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="how-incremental-sql-models-work">How incremental SQL models work&lt;/h2>&lt;p>Incremental SQL models follow this workflow:&lt;/p>
&lt;ol>
&lt;li>Reference previous state using &lt;code>this.DeRef()&lt;/code> with &lt;code>pre_existing=true&lt;/code>&lt;/li>
&lt;li>Reference delta models that represent changes since the baseline checkpoint&lt;/li>
&lt;li>Collect new rows from upstream sources that arrived since the baseline checkpoint&lt;/li>
&lt;li>If previous state exists, merge it with new data; otherwise perform a full scan&lt;/li>
&lt;li>Materialize the result as a table, view, or ephemeral model&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="key-advantages" data-heading="Key advantages" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="key-advantages">Key advantages&lt;/h3>&lt;p>Profiles handles the complexity for you:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Automatic creation&lt;/strong>: Delta models are automatically generated for append-only inputs&lt;/li>
&lt;li>&lt;strong>Automatic cleanup&lt;/strong>: Old materials are cleaned up based on retention periods&lt;/li>
&lt;li>&lt;strong>Automatic build order&lt;/strong>: Dependency resolution ensures correct execution order&lt;/li>
&lt;li>&lt;strong>No manual backfill required&lt;/strong>: Full refresh mode handles first run automatically&lt;/li>
&lt;li>&lt;strong>Per-model incremental base&lt;/strong>: If one entity var changes, others can still run incrementally&lt;/li>
&lt;li>&lt;strong>Efficient time management&lt;/strong>: Large changes may take longer, but subsequent runs remain fast&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="basic-template-structure" data-heading="Basic template structure" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="basic-template-structure">Basic template structure&lt;/h2>&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">models&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">example_incremental_model&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">model_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sql_template&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">model_spec&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">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">timestamp&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">materialization&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">output_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">table&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">single_sql&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- set rootIncrementalPreReqs = this.RootIncrementalPreReqs() -%}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- set lastThis = this.DeRef(pre_existing=true, dependency=&amp;#34;optional&amp;#34;, checkpoint_name=&amp;#34;baseline&amp;#34;, prereqs=rootIncrementalPreReqs) -%}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% set events_delta = this.DeRef(&amp;#34;inputs/events/incr_delta_tbl&amp;#34;, dependency=&amp;#34;coercive&amp;#34;, baseline_name=&amp;#34;baseline&amp;#34;, prereqs=[lastThis]) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% set events_full = this.DeRef(&amp;#34;inputs/events&amp;#34;, prereqs=[events_delta.Except()]) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {# All DeRef before this line. Note that DeRef should not be put in conditionals. DeRef mark dependencies — use prereqs for conditional dependencies #}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% if lastThis.IsEnabled() &amp;amp;&amp;amp; events_delta.IsEnabled() %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -- Incremental mode: merge with baseline
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT * FROM {{ lastThis }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> UNION ALL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT * FROM {{ events_delta }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% else %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -- Full refresh mode: process all data
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT * FROM {{ events_full }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% endif %}&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">contract&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">is_append_only&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>Tip:&lt;/strong>
Note the following:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Incremental SQL models work on append-only inputs&lt;/strong>: The upstream inputs must have &lt;code>contract: is_append_only: true&lt;/code> to enable delta model generation.&lt;/li>
&lt;li>&lt;strong>Also works on append-only SQL models&lt;/strong>: Incremental SQL models can build on other append-only SQL models, even ephemeral ones.&lt;/li>
&lt;li>Set &lt;code>is_append_only: false&lt;/code> for incremental SQL models that merge or update data.&lt;/li>
&lt;li>Set &lt;code>is_append_only: true&lt;/code> only if your model truly only appends new rows without modifying existing ones.&lt;/li>
&lt;li>Profiles also supports keeping the SQL template in another file and referencing it using &lt;code>{% exec %} {{ this.ReadFile(&amp;quot;file/path&amp;quot;) }} {% endexec %}&lt;/code>.&lt;/li>
&lt;/ul>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="key-concepts" data-heading="Key concepts" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="key-concepts">Key concepts&lt;/h2>&lt;p>This section explains the key concepts of incremental SQL models.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="previous-state-reference" data-heading="Previous state reference" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="previous-state-reference">Previous state reference&lt;/h3>&lt;p>Use &lt;code>this.DeRef()&lt;/code> with &lt;code>pre_existing=true&lt;/code> to reference the previous materialization of the current model:&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">{%- set lastThis = this.DeRef(
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> pre_existing=true,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> dependency=&amp;#34;optional&amp;#34;,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> checkpoint_name=&amp;#34;baseline&amp;#34;) -%}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This looks for a previous materialization, uses it as a baseline checkpoint, and returns &lt;code>nil&lt;/code> if no baseline exists (enabling full refresh mode).&lt;/p>
&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/deref-reference/" >DeRef Reference&lt;/a> for complete syntax and usage.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="collecting-new-data" data-heading="Collecting new data" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="collecting-new-data">Collecting new data&lt;/h3>&lt;p>When running incrementally, collect only new data that arrived since the baseline checkpoint. Profiles automatically handles this for append-only inputs when you reference them with the appropriate baseline context using &lt;code>baseline_name&lt;/code> that matches the &lt;code>checkpoint_name&lt;/code> used for &lt;code>lastThis&lt;/code>.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="incremental-vs-full-refresh-modes" data-heading="Incremental vs. full refresh modes" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="incremental-vs-full-refresh-modes">Incremental vs. full refresh modes&lt;/h3>&lt;ul>
&lt;li>&lt;strong>Incremental mode&lt;/strong> (when baseline exists): Merges previous state with new data, processing only changes since the last checkpoint.&lt;/li>
&lt;li>&lt;strong>Full refresh mode&lt;/strong> (when no baseline exists): Processes all historical data, used on first run or when baseline is unavailable.&lt;/li>
&lt;/ul>
&lt;p>See the &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/#incremental-vs-full-refresh" >Checkpoints and Baselines&lt;/a> guide for more information on these modes.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-monthly-active-users-mau" data-heading="Example: Monthly Active Users (MAU)" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="example-monthly-active-users-mau">Example: Monthly Active Users (MAU)&lt;/h2>&lt;p>This example demonstrates an incremental input window model pattern for tracking monthly active users, where an incremental SQL model maintains a rolling window of active days, and an entity var references it to compute MAU.&lt;/p>
&lt;p>&lt;strong>Input configuration&lt;/strong> (&lt;code>inputs.yaml&lt;/code>):&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">inputs&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">events&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&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">PROD.ANALYTICS.EVENTS&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">contract&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">is_append_only&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">is_event_stream&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">timestamp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Incremental SQL model&lt;/strong> (&lt;code>sql_models.yaml&lt;/code>):&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">models&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">recent_user_activity&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">model_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sql_template&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">model_spec&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">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">timestamp&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">materialization&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">output_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">table&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">single_sql&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- set rootIncrementalPreReqs = this.RootIncrementalPreReqs() -%}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- set lastThis = this.DeRef(pre_existing=true, dependency=&amp;#34;optional&amp;#34;, checkpoint_name=&amp;#34;baseline&amp;#34;, prereqs=rootIncrementalPreReqs) -%}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% set events_delta = this.DeRef(&amp;#34;inputs/events/incr_delta_tbl&amp;#34;, dependency=&amp;#34;coercive&amp;#34;, baseline_name=&amp;#34;baseline&amp;#34;, prereqs=[lastThis]) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% set events_full = this.DeRef(&amp;#34;inputs/events&amp;#34;, prereqs=[events_delta.Except()]) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {# All DeRef before this line. Note that DeRef should not be put in conditionals. DeRef mark dependencies — use prereqs for conditional dependencies #}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT user_id, active_day
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> FROM (
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- if lastThis.IsEnabled() %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -- Incremental mode: merge previous active days with new events
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT DISTINCT user_id, CAST(timestamp AS DATE) AS active_day
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> FROM (
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT user_id, timestamp FROM {{ events_delta }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> UNION ALL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT user_id, active_day AS timestamp FROM {{ lastThis }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- else %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> -- Full refresh mode: process all events
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT DISTINCT user_id, CAST(timestamp AS DATE) AS active_day
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> FROM {{ events_full }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- endif %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> WHERE active_day &amp;gt;= DATEADD(&amp;#39;day&amp;#39;, -365, {{ end_time_sql }})&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">ids&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">select&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">type&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">entity&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">contract&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">is_append_only&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This incremental SQL model has &lt;code>is_append_only: false&lt;/code> because it maintains a rolling window that removes old data (older than 365 days). Incremental SQL models that merge or update data should set &lt;code>is_append_only: false&lt;/code> — only set &lt;code>is_append_only: true&lt;/code> if your model truly only appends new rows without modifying existing ones.&lt;/p>
&lt;p>&lt;strong>Entity variable&lt;/strong> (&lt;code>profiles.yaml&lt;/code>):&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">entity_var&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">monthly_active_users&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">COUNT(DISTINCT 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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/recent_user_activity&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">active_day &amp;gt;= DATEADD(&amp;#39;day&amp;#39;, -30, {{ end_time_sql }})&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Number of distinct users active in the past 30 days&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="how-it-works" data-heading="How it works" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="how-it-works">How it works&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Input configuration&lt;/strong>: The &lt;code>events&lt;/code> input has &lt;code>contract: is_append_only: true&lt;/code>, enabling incremental processing.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Incremental SQL model&lt;/strong>: The &lt;code>recent_user_activity&lt;/code> model:&lt;/p>
&lt;ul>
&lt;li>References its previous materialization using &lt;code>lastThis&lt;/code> with &lt;code>pre_existing=true&lt;/code>&lt;/li>
&lt;li>Collects new events from &lt;code>events_delta&lt;/code> when running incrementally&lt;/li>
&lt;li>Merges previous active days with new event dates using &lt;code>UNION ALL&lt;/code> and &lt;code>DISTINCT&lt;/code>&lt;/li>
&lt;li>Filters to maintain only the last 365 days of activity&lt;/li>
&lt;li>Handles full refresh mode when no baseline exists&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Entity var reference&lt;/strong>: The &lt;code>monthly_active_users&lt;/code> entity var references the incremental SQL model and filters to the past 30 days, counting distinct users from the pre-computed model.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>This pattern is efficient because the SQL model maintains state incrementally (only processing new events), and the entity var performs a simple aggregation on the pre-computed model.&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/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Issue&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Model fails on first run&lt;/td>
&lt;td>Ensure your model handles cases when &lt;code>lastThis.IsEnabled()&lt;/code> is both false and true. Use &lt;code>events_full&lt;/code> with &lt;code>prereqs=[events_delta.Except()]&lt;/code> to ensure proper fallback when baseline doesn&amp;rsquo;t exist&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>New data not being processed&lt;/td>
&lt;td>Verify that upstream inputs have &lt;code>contract: is_append_only: true&lt;/code> configured and that your &lt;code>baseline_name&lt;/code> matches the &lt;code>checkpoint_name&lt;/code> used for &lt;code>lastThis&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Incorrect merge results&lt;/td>
&lt;td>Check that your merge logic correctly handles both existing and new entities. Use appropriate SQL joins, UNION ALL patterns, or ordering/de-duplication functions based on your use case&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Performance not improving&lt;/td>
&lt;td>Ensure your filtering logic correctly identifies only new data and that your merge logic is efficient. Verify that delta models are being used instead of full inputs&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>DeRef&lt;/code> errors&lt;/td>
&lt;td>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/deref-reference/" >DeRef Reference&lt;/a> for syntax and troubleshooting&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SQL syntax errors&lt;/td>
&lt;td>Note that SQL syntax varies by warehouse. &lt;code>DATEADD&lt;/code> is Snowflake/Redshift syntax. For BigQuery, use &lt;code>DATE_SUB&lt;/code>; for Databricks, use &lt;code>date_sub&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="avoiding-cycles-and-infinite-regress" data-heading="Avoiding cycles and infinite regress" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h3 id="avoiding-cycles-and-infinite-regress">Avoiding cycles and infinite regress&lt;/h3>&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">Incremental features are powerful but need to be used carefully to avoid cycles and infinite regress.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;p>&lt;strong>Important: All DeRef before conditionals&lt;/strong>&lt;/p>
&lt;p>All &lt;code>DeRef&lt;/code> calls must be placed before any conditional logic (&lt;code>if&lt;/code> statements). Profiles needs to discover all dependencies during the dependency discovery phase, which happens before SQL execution. If &lt;code>DeRef&lt;/code> is inside a conditional, Profiles cannot determine dependencies correctly.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">CORRECT&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">All&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">at&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">the&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">top&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inputs/events/incr_delta_tbl&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">prereqs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">IsEnabled&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">materials&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">here&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">endif&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">WRONG&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">inside&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">conditional&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">breaks&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">discovery&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">some_condition&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">material&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;some/model&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ERROR&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">endif&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Common mistakes and how to avoid them:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Infinite regress: Self pre-existing DeRef must be optional&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">WRONG&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">mandatory&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">self&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">reference&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">creates&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">infinite&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">regress&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;normal&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">CORRECT&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">self&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">reference&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">must&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">be&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">optional&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">checkpoint_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Why&lt;/strong>: Without &lt;code>dependency=&amp;quot;optional&amp;quot;&lt;/code>, Profiles tries to create infinite historical chain of materials.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Cycle: Missing pre_existing=true flag&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">WRONG&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">missing&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">creates&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">cycle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">checkpoint_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">CORRECT&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">must&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">specify&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">checkpoint_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Why&lt;/strong>: Without &lt;code>pre_existing=true&lt;/code>, the model depends on itself in the same time context, creating a cycle.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Inefficient: Delta derefs must be conditional&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">INEFFICIENT&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">runs&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">even&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">full&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">refresh&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mode&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inputs/events/incr_delta_tbl&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">baseline_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">CORRECT&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">only&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">runs&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">when&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">baseline&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">exists&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">checkpoint_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inputs/events/incr_delta_tbl&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;coercive&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">baseline_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">prereqs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Why&lt;/strong>: Without &lt;code>prereqs=[lastThis]&lt;/code>, delta model runs even during full refresh, wasting compute. Var tables may also run unnecessarily.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>&lt;strong>Profiles protections:&lt;/strong>&lt;/p>
&lt;p>Profiles has built-in protections to catch these issues:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Cycle detection&lt;/strong>: Graph validation catches same-time-context cycles during dependency resolution&lt;/li>
&lt;li>&lt;strong>Infinite regress detection&lt;/strong>: If &amp;gt;10,000 temporary sequence numbers are created, Profiles throws an error with diagnostic information&lt;/li>
&lt;li>&lt;strong>Helpful error messages&lt;/strong>: Errors include the call chain, recent material allocations, and suggestions for fixing the issue&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Debug tips:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Check that all self-referencing DeRefs have &lt;code>dependency=&amp;quot;optional&amp;quot;&lt;/code>&lt;/li>
&lt;li>Verify all pre-existing references include &lt;code>pre_existing=true&lt;/code>&lt;/li>
&lt;li>Ensure delta model DeRefs include &lt;code>prereqs=[lastThis]&lt;/code> to make them conditional&lt;/li>
&lt;li>Use &lt;code>baseline_name&lt;/code> matching the &lt;code>checkpoint_name&lt;/code> for consistency&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="see-more" data-heading="See more" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" data-title="Incremental SQL Models" -->
&lt;h2 id="see-more">See more&lt;/h2>&lt;ul>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/incremental-sql-models/" >Incremental SQL Models Overview&lt;/a>: Conceptual introduction to incremental SQL models&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" >How to Make Features Incremental&lt;/a>: Step-by-step guide to convert features to incremental&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/deref-reference/" >DeRef Reference&lt;/a>: Complete reference for &lt;code>this.DeRef()&lt;/code> syntax and usage&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a>: Understanding checkpoints and how they enable incremental computation&lt;/li>
&lt;/ul></description></item><item><title>Archive: How to Make Features Incremental</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/</guid><description>
&lt;p>This guide walks you through converting features to incremental mode in Profiles.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="prerequisites" data-heading="Prerequisites" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="prerequisites">Prerequisites&lt;/h2>&lt;p>Before making a feature incremental, make sure that:&lt;/p>
&lt;ul>
&lt;li>Your input sources are append-only and have reliable &lt;code>occurred_at_col&lt;/code> timestamps&lt;/li>
&lt;li>The feature can be expressed using &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/" >supported incremental patterns&lt;/a>&lt;/li>
&lt;li>You understand how &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a> work in Profiles&lt;/li>
&lt;/ul>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>Not all features can be incremental.&lt;/strong>&lt;/p>
&lt;p>Features that require scanning all historical data (such as median or percentile calculations) &lt;strong>cannot&lt;/strong> use incremental computation. For such cases, consider using &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/timegrains/" >Timegrains&lt;/a> and &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/optimizations/" >bundling&lt;/a>.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="step-1-configure-input-contracts" data-heading="Step 1: Configure input contracts" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="step-1-configure-input-contracts">Step 1: Configure input contracts&lt;/h2>&lt;p>Before making features incremental, you must configure all input sources and SQL models with the &lt;code>is_append_only&lt;/code> contract. This applies to inputs and SQL models (which can also be ephemeral).&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="verify-append-only-behavior" data-heading="Verify append-only behavior" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="verify-append-only-behavior">Verify append-only behavior&lt;/h3>&lt;p>Before marking an input as append-only, verify that it truly only appends new rows and never updates or deletes existing ones:&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Check business semantics&lt;/strong>: Event/fact tables (page views, purchases, clicks) are typically append-only. Dimension tables (user profiles, account settings) that update rows in place are &lt;strong>not&lt;/strong> append-only.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Run a warehouse query&lt;/strong>: Check for duplicate primary keys that would indicate updates:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">entity_id_column&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&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="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">your_input_table&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="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">entity_id_column&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="k">HAVING&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Tip:&lt;/strong>
Inspect results to distinguish genuine duplicate events from row updates.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;ol start="3">
&lt;li>&lt;strong>Check downstream usage&lt;/strong>: If a downstream model selects the latest attribute value (like current subscription status), the input likely receives updates and should &lt;strong>not&lt;/strong> be marked append-only.&lt;/li>
&lt;/ol>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>When in doubt, treat an input as not append-only.&lt;/strong>&lt;/p>
&lt;p>Incorrectly marking a mutable input as &lt;code>is_append_only: true&lt;/code> leads to incorrect incremental results that are difficult to diagnose.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="input-example" data-heading="Input example" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="input-example">Input example&lt;/h3>&lt;p>Add the following to each verified append-only input in your &lt;code>inputs.yaml&lt;/code>:&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">inputs&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">orders&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&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">PROD.ANALYTICS.ORDERS&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">contract&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">is_append_only&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">is_event_stream&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">order_timestamp&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="sql-model-example" data-heading="SQL model example" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="sql-model-example">SQL model example&lt;/h3>&lt;p>You can also create append-only SQL models that filter or transform inputs. Add this to your &lt;code>sql_models.yaml&lt;/code>:&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">models&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">purchase_events&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">model_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sql_template&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">model_spec&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">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">timestamp&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">materialization&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">output_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">table&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">single_sql&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% with events = this.DeRef(&amp;#34;inputs/events&amp;#34;) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT * FROM {{ events }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> WHERE event_name = &amp;#39;purchase&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% endwith %}&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">contract&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">is_append_only&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">is_event_stream&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>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This SQL model filters events to only purchases and is marked as &lt;code>is_append_only: true&lt;/code>, making it usable as an incremental source.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="ephemeral-sql-models" data-heading="Ephemeral SQL models" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="ephemeral-sql-models">Ephemeral SQL models&lt;/h3>&lt;p>Ephemeral SQL models (&lt;code>output_type: ephemeral&lt;/code>) that sit on top of append-only inputs can also be marked as &lt;code>is_append_only: true&lt;/code>. This is useful for filtering or transforming inputs without materializing intermediate tables.&lt;/p>
&lt;p>Only mark an ephemeral model as append-only if:&lt;/p>
&lt;ul>
&lt;li>All upstream inputs are append-only&lt;/li>
&lt;li>The model only filters, renames, or transforms columns (no joins with mutable dimension tables)&lt;/li>
&lt;li>The output is itself append-only (no aggregations that change with updates)&lt;/li>
&lt;/ul>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">All inputs and SQL models used by incremental features must have &lt;code>contract: is_append_only: true&lt;/code>. SQL models can also be ephemeral. Without this configuration, the project will throw an error when you try to run incremental features.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="complete-example-simple-incremental-feature" data-heading="Complete example: Simple incremental feature" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="complete-example-simple-incremental-feature">Complete example: Simple incremental feature&lt;/h3>&lt;p>The following example shows a complete setup for a simple incremental feature that tracks total purchase value:&lt;/p>
&lt;p>&lt;strong>Input configuration&lt;/strong> (&lt;code>inputs.yaml&lt;/code>):&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">inputs&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">orders&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&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">PROD.ANALYTICS.ORDERS&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">contract&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">is_append_only&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">is_event_stream&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">order_timestamp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Entity var&lt;/strong> (&lt;code>profiles.yaml&lt;/code>):&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">entity_var&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">total_purchases&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{orders.value}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.total_purchases}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Total purchase value across all orders&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This example shows:&lt;/p>
&lt;ul>
&lt;li>Input configured with &lt;code>contract: is_append_only: true&lt;/code>&lt;/li>
&lt;li>Entity var using &lt;code>SUM&lt;/code> aggregation with &lt;code>merge: SUM({{rowset.total_purchases}})&lt;/code>&lt;/li>
&lt;li>Profiles automatically handles incremental computation&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="step-2-identify-the-feature-pattern" data-heading="Step 2: Identify the feature pattern" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="step-2-identify-the-feature-pattern">Step 2: Identify the feature pattern&lt;/h2>&lt;p>Determine which incremental pattern your feature matches:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Simple aggregations&lt;/strong>: &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, &lt;code>SUM&lt;/code>, &lt;code>COUNT&lt;/code> - See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a>&lt;/li>
&lt;li>&lt;strong>Compound aggregations&lt;/strong>: &lt;code>AVG&lt;/code>, &lt;code>MIN_BY&lt;/code>/&lt;code>MAX_BY&lt;/code>, arrays, booleans - See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>&lt;/li>
&lt;li>&lt;strong>Window function replacements&lt;/strong>: &lt;code>LAST_VALUE&lt;/code> -&amp;gt; &lt;code>MAX_BY&lt;/code>, &lt;code>FIRST_VALUE&lt;/code> -&amp;gt; &lt;code>MIN_BY&lt;/code> - See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/#replacing-window-functions" >Replacing window functions&lt;/a>&lt;/li>
&lt;li>&lt;strong>Complex patterns&lt;/strong>: Stateful processing, running totals, activity windows - See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/" >Incremental Features&lt;/a> for a pattern selection guide and detailed examples.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="step-3-add-the-merge-property" data-heading="Step 3: Add the &lt;code>merge&lt;/code> property" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="step-3-add-the-merge-property">Step 3: Add the &lt;code>merge&lt;/code> property&lt;/h2>&lt;p>Add a &lt;code>merge:&lt;/code> property to your &lt;code>entity_var&lt;/code> definition in your &lt;code>profiles.yaml&lt;/code> file. This property defines how to combine previous feature values with new data.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="simple-aggregators" data-heading="Simple aggregators" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="simple-aggregators">Simple aggregators&lt;/h3>&lt;p>For &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, &lt;code>SUM&lt;/code>, &lt;code>COUNT&lt;/code>, and similar functions:&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">entity_var&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">first_event_time&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{rowset.first_event_time}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Earliest timestamp of any event&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="average-using-component-features" data-heading="Average using component features" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="average-using-component-features">Average using component features&lt;/h3>&lt;p>For &lt;code>AVG&lt;/code>, break it into sum and count components. Define three separate &lt;code>entity_var&lt;/code> entries at the same level in your &lt;code>profiles.yaml&lt;/code>:&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">entity_var&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">sum_of_scores&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{game_events.score}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.sum_of_scores}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/game_events&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Sum of scores (used for average calculation)&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">entity_var&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">count_of_scores&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">COUNT({{game_events.score}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.count_of_scores}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/game_events&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Count of scores (used for average calculation)&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">entity_var&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">avg_score&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;CASE WHEN {{user.count_of_scores}} &amp;gt; 0 THEN {{user.sum_of_scores}} / {{user.count_of_scores}} ELSE 0 END&amp;#34;&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Average score across all games&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">&lt;p>&lt;strong>Features referencing other features&lt;/strong>&lt;/p>
&lt;p>When a feature references another feature (like &lt;code>{{user.sum_of_scores}}&lt;/code>), it doesn&amp;rsquo;t need a &lt;code>merge:&lt;/code> clause if it&amp;rsquo;s just performing a calculation on incrementally maintained features. The referenced features (&lt;code>sum_of_scores&lt;/code> and &lt;code>count_of_scores&lt;/code>) maintain their incremental state, and the calculation (&lt;code>avg_score&lt;/code>) is computed on-the-fly from those values.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="use-incremental-sources" data-heading="Use incremental sources" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="use-incremental-sources">Use incremental sources&lt;/h3>&lt;p>You can also make features incremental by pointing to an incremental source (such as a &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/#delta-models" >delta model&lt;/a> or incremental input window). Even if the &lt;code>entity_var&lt;/code> SQL runs a full aggregation, the scan volume stays small because the source is already delta-restricted:&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">entity_var&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">recent_purchases&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{recent_orders.value}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders/incr_delta_tbl&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Purchases from recent data only&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="step-4-define-merge-logic" data-heading="Step 4: Define merge logic" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="step-4-define-merge-logic">Step 4: Define merge logic&lt;/h2>&lt;p>The &lt;code>merge:&lt;/code> clause must match the aggregation function in &lt;code>select:&lt;/code>. Common patterns:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Select function&lt;/th>
&lt;th>Merge function&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>MIN(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>MIN({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>MAX(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>MAX({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>SUM(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>SUM({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>COUNT(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>SUM({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>MAX_BY(val, ord)&lt;/code>&lt;/td>
&lt;td>&lt;code>MAX_BY({{rowset.feature}}, {{rowset.feature_by_param}})&lt;/code> + &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/#min_by--max_by-with-ordering-helper" >helper var&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>MIN_BY(val, ord)&lt;/code>&lt;/td>
&lt;td>&lt;code>MIN_BY({{rowset.feature}}, {{rowset.feature_by_param}})&lt;/code> + &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/#min_by--max_by-with-ordering-helper" >helper var&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ARRAY_AGG(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>ARRAY_UNION_AGG({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>BOOLOR_AGG(...)&lt;/code>&lt;/td>
&lt;td>&lt;code>BOOLOR_AGG({{rowset.feature_name}})&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>For complete &lt;code>merge&lt;/code> syntax, see &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a> and &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="which-merge-function-should-i-use" data-heading="Which &lt;code>merge&lt;/code> function should I use?" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="which-merge-function-should-i-use">Which &lt;code>merge&lt;/code> function should I use?&lt;/h3>&lt;p>The &lt;code>merge&lt;/code> function must match your aggregation type. For &lt;code>COUNT&lt;/code>, always use &lt;code>SUM&lt;/code> in the &lt;code>merge&lt;/code> property (summing counts, not counting counts). See the table above for the correct merge function for each aggregation type.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="step-5-use-merge_where-when-needed" data-heading="Step 5: Use &lt;code>merge_where&lt;/code> when needed" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="step-5-use-merge_where-when-needed">Step 5: Use &lt;code>merge_where&lt;/code> when needed&lt;/h2>&lt;p>For complex merges, use &lt;code>merge_where:&lt;/code> to restrict merging to only changed rows. Define separate &lt;code>entity_var&lt;/code> entries at the same level in your &lt;code>profiles.yaml&lt;/code>:&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">entity_var&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">timestamp&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{game_events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.timestamp}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/game_events&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">game_events.event_type}} = &amp;#34;BREAK&amp;#34;&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Timestamp of the most recent break event (used for score lookup)&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">entity_var&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">score_at_last_break&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">any_value({{game_events.score}})&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">game_events.timestamp}} = {{user.timestamp}}&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">any_value({{game_events.score}})&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">merge_where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">rowset.timestamp}} = {{user.timestamp}}&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/game_events&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Score at the most recent break event&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The &lt;code>timestamp&lt;/code> entity var is marked with &lt;code>is_feature: false&lt;/code> since it&amp;rsquo;s an intermediate calculation used by &lt;code>score_at_last_break&lt;/code>.&lt;/p>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Tip:&lt;/strong>
Mark helper entity vars with &lt;code>is_feature: false&lt;/code> when they&amp;rsquo;re intermediate calculations used by other features. This prevents them from appearing as features in your output while still allowing them to be referenced by other entity vars.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="when-merge-is-not-needed" data-heading="When merge is not needed" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="when-merge-is-not-needed">When merge is not needed&lt;/h2>&lt;p>Not every entity var requires a &lt;code>merge&lt;/code> clause to participate in an incremental project:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Derived-only vars&lt;/strong> (no &lt;code>from&lt;/code> clause) that reference other entity vars are recomputed from their incrementally maintained dependencies. Since they don&amp;rsquo;t read from input sources directly, they don&amp;rsquo;t need their own merge logic:&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">entity_var&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">days_since_last_seen&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;DATEDIFF(day, {{user.last_seen}}, {{ end_time_sql }})&amp;#34;&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Days since the user was last seen&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Vars from window-bounded incremental tables&lt;/strong> that read from an &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Model&lt;/a> maintaining a sliding window. The SQL model handles state incrementally, and the entity var recomputes from the bounded window each run:&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">entity_var&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">active_days_in_past_7_days&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">count(distinct active_day)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/recent_active_days&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">active_day &amp;gt;= DATEADD(day, -7, {{ end_time_sql }})&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Days active in the last 7 days&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="step-6-test-your-implementation" data-heading="Step 6: Test your implementation" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="step-6-test-your-implementation">Step 6: Test your implementation&lt;/h2>&lt;ol>
&lt;li>Run &lt;code>pb run&lt;/code> to verify the feature computes correctly&lt;/li>
&lt;li>Compare incremental results with a full refresh to ensure accuracy&lt;/li>
&lt;li>Monitor run times to verify improvement&lt;/li>
&lt;/ol>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">The first run performs a full refresh to establish the baseline checkpoint. Subsequent runs use incremental computation.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="verifying-incremental-behavior" data-heading="Verifying incremental behavior" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h3 id="verifying-incremental-behavior">Verifying incremental behavior&lt;/h3>&lt;p>To verify your feature is running incrementally:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Check run times&lt;/strong>: Incremental runs should be faster than full refresh runs (after the first run)&lt;/li>
&lt;li>&lt;strong>Compare results&lt;/strong>: Run with incremental mode and compare results with a full refresh to ensure they match&lt;/li>
&lt;li>&lt;strong>Monitor checkpoint usage&lt;/strong>: Verify that checkpoints are being created and used in subsequent runs&lt;/li>
&lt;/ul>
&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/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Issue&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Feature values are incorrect&lt;/td>
&lt;td>&lt;ul>&lt;li>Verify that your &lt;code>merge:&lt;/code> clause correctly matches the aggregation logic&lt;/li>&lt;li>Ensure that your input sources are append-only or have reliable timestamps&lt;/li>&lt;li>Check that you are not missing edge cases in merge logic&lt;/li>&lt;li>Compare incremental results with a full refresh to identify discrepancies&lt;/li>&lt;/ul>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Performance not improving&lt;/td>
&lt;td>&lt;ul>&lt;li>Verify that your input sources are properly configured for incremental processing&lt;/li>&lt;li>Check that delta models are being used correctly&lt;/li>&lt;li>Ensure your data warehouse supports efficient timestamp filtering&lt;/li>&lt;li>Monitor checkpoint creation and usage&lt;/li>&lt;/ul>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Merge errors&lt;/td>
&lt;td>&lt;ul>&lt;li>Verify that all aggregators in &lt;code>select:&lt;/code> have corresponding merge logic&lt;/li>&lt;li>Check that merge functions match the aggregation type&lt;/li>&lt;li>Ensure &lt;code>merge_where:&lt;/code> conditions are correct if used&lt;/li>&lt;li>Review &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a> and &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a> for correct syntax&lt;/li>&lt;/ul>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>The first run is slow&lt;/td>
&lt;td>This is expected. The first run always performs a full refresh to establish the baseline checkpoint. Subsequent runs use incremental computation and should be faster.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="see-more" data-heading="See more" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" data-title="How to Make Features Incremental" -->
&lt;h2 id="see-more">See more&lt;/h2>&lt;ul>
&lt;li>Explore &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/" >Incremental Features&lt;/a> for pattern selection guide&lt;/li>
&lt;li>Learn about &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a>&lt;/li>
&lt;li>Learn about &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>&lt;/li>
&lt;li>Learn about &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/li>
&lt;li>Learn about &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Archive: How to Migrate a Project to Incremental</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/</guid><description>
&lt;p>This tutorial walks you through migrating an entire Profiles project from non-incremental to incremental mode. It covers the systematic workflow: auditing your project, configuring inputs, converting features, eliminating input vars, and validating results.&lt;/p>
&lt;p>For converting individual features, see &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" >How to Make Features Incremental&lt;/a>.&lt;/p>
&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/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="overview">Overview&lt;/h2>&lt;p>An incremental Profiles project processes only new and changed data on each run, rather than reprocessing all historical data. This reduces compute costs, improves latency, and enables faster data freshness.&lt;/p>
&lt;p>Migration follows a specific order of operations:&lt;/p>
&lt;ol>
&lt;li>Audit your project&lt;/li>
&lt;li>Verify and mark append-only inputs&lt;/li>
&lt;li>Handle ephemeral SQL models&lt;/li>
&lt;li>Convert entity vars (add &lt;code>merge&lt;/code> clauses)&lt;/li>
&lt;li>Eliminate input vars&lt;/li>
&lt;li>Validate with &lt;code>--rebase_incremental&lt;/code>&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="prerequisites" data-heading="Prerequisites" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="prerequisites">Prerequisites&lt;/h2>&lt;p>Before starting migration, make sure that:&lt;/p>
&lt;ul>
&lt;li>You have a working, non-incremental Profiles project that runs successfully&lt;/li>
&lt;li>You understand &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/" >Incremental Features&lt;/a> concepts&lt;/li>
&lt;li>You understand &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a>&lt;/li>
&lt;li>You have access to run queries against your data warehouse&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="1-audit-your-project" data-heading="1: Audit your project" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="1-audit-your-project">1: Audit your project&lt;/h2>&lt;p>Before making any changes, inventory your project to understand what needs to migrate.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="identify-all-components" data-heading="Identify all components" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="identify-all-components">Identify all components&lt;/h3>&lt;p>Review your project files and list:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Resource&lt;/th>
&lt;th style="text-align:left">File name&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">Inputs&lt;/td>
&lt;td style="text-align:left">&lt;code>inputs.yaml&lt;/code>&lt;/td>
&lt;td style="text-align:left">All input sources and their table types&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">SQL models&lt;/td>
&lt;td style="text-align:left">&lt;code>sql_models.yaml&lt;/code>&lt;/td>
&lt;td style="text-align:left">All SQL template models, noting which are ephemeral&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Entity vars&lt;/td>
&lt;td style="text-align:left">&lt;code>profiles.yaml&lt;/code>&lt;/td>
&lt;td style="text-align:left">All entity vars, their aggregation functions, and &lt;code>from&lt;/code> sources&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">Input vars&lt;/td>
&lt;td style="text-align:left">&lt;code>profiles.yaml&lt;/code>&lt;/td>
&lt;td style="text-align:left">All input vars (must be eliminated or converted)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="classify-inputs" data-heading="Classify inputs" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="classify-inputs">Classify inputs&lt;/h3>&lt;p>For each input, determine whether it is append-only or mutable:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Input type&lt;/th>
&lt;th>Append-only&lt;/th>
&lt;th>Examples&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Event streams (facts)&lt;/td>
&lt;td>Yes&lt;/td>
&lt;td>Page views, purchases, clicks, logins&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Slowly-changing dimensions&lt;/td>
&lt;td>No&lt;/td>
&lt;td>User profiles, account settings, subscription status&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Snapshot tables&lt;/td>
&lt;td>No&lt;/td>
&lt;td>Daily balance snapshots, inventory levels&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="check-for-input-vars" data-heading="Check for input vars" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="check-for-input-vars">Check for input vars&lt;/h3>&lt;p>Input vars scan all input data on every run and &lt;strong>cannot be made incremental&lt;/strong>. If your project has input vars, you must convert them (see Step 5).&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="2-verify-and-mark-append-only-inputs" data-heading="2: Verify and mark append-only inputs" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="2-verify-and-mark-append-only-inputs">2: Verify and mark append-only inputs&lt;/h2>&lt;p>For a model to participate in incremental processing, its upstream inputs must be append-only. This step ensures you correctly identify and mark them.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="verify-append-only-behavior" data-heading="Verify append-only behavior" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="verify-append-only-behavior">Verify append-only behavior&lt;/h3>&lt;p>Use these three checks to verify an input is truly append-only:&lt;/p>
&lt;p>&lt;strong>1. Business semantics check&lt;/strong>&lt;/p>
&lt;p>Ask: Is the underlying source a fact table (events) or a slowly-changing dimension?&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Fact tables&lt;/strong> (events, transactions, clicks) are typically append-only — rows represent immutable events&lt;/li>
&lt;li>&lt;strong>Dimension tables&lt;/strong> (user profiles, account settings) are &lt;strong>not&lt;/strong> append-only — rows are updated in place&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>2. Warehouse verification query&lt;/strong>&lt;/p>
&lt;p>Run this query against your warehouse to check for duplicate or updated rows:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">entity_id_column&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&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="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">your_input_table&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="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">entity_id_column&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="k">HAVING&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If this returns rows, inspect whether duplicates represent distinct events (append-only) or updates to the same record (not append-only).&lt;/p>
&lt;p>&lt;strong>3. Downstream usage inspection&lt;/strong>&lt;/p>
&lt;p>Check how the input is used in SQL models and entity vars. If a model selects the &amp;ldquo;latest&amp;rdquo; attribute value (such as current subscription status or country), that suggests the input receives updates and is NOT append-only.&lt;/p>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;p>&lt;strong>When in doubt about whether an input is append-only, treat it as not append-only.&lt;/strong>&lt;/p>
&lt;p>Incorrectly marking a mutable input as append-only leads to incorrect incremental results that are difficult to diagnose.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="mark-append-only-inputs" data-heading="Mark append-only inputs" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="mark-append-only-inputs">Mark append-only inputs&lt;/h3>&lt;p>For each verified append-only input, add the contract:&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">inputs&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">events&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&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">PROD.ANALYTICS.EVENTS&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">contract&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">is_append_only&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">is_event_stream&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">event_timestamp&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Some key fields in the contract are listed below:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align:left">Field&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>is_append_only&lt;/code>&lt;/td>
&lt;td style="text-align:left">Enables delta model generation for incremental processing&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;code>is_event_stream&lt;/code>&lt;/td>
&lt;td style="text-align:left">Indicates this is an event stream&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left">&lt;code>occurred_at_col&lt;/code>&lt;/td>
&lt;td style="text-align:left">The timestamp column used for time-range filtering. Required for incremental inputs.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="3-handle-ephemeral-sql-models" data-heading="3: Handle ephemeral SQL models" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="3-handle-ephemeral-sql-models">3: Handle ephemeral SQL models&lt;/h2>&lt;p>Ephemeral SQL models defined on top of append-only inputs can also participate in incremental processing.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="identify-eligible-ephemeral-models" data-heading="Identify eligible ephemeral models" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="identify-eligible-ephemeral-models">Identify eligible ephemeral models&lt;/h3>&lt;p>Look for SQL models with &lt;code>output_type: ephemeral&lt;/code> that:&lt;/p>
&lt;ul>
&lt;li>Read from append-only inputs&lt;/li>
&lt;li>Only filter, rename, or transform columns (no aggregations or joins with mutable sources)&lt;/li>
&lt;li>Produce output that is itself append-only&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="mark-ephemeral-models-as-append-only" data-heading="Mark ephemeral models as append-only" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="mark-ephemeral-models-as-append-only">Mark ephemeral models as append-only&lt;/h3>&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">models&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">purchase_events&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">model_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sql_template&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">model_spec&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">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">timestamp&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">materialization&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">output_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ephemeral&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">single_sql&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% with events = this.DeRef(&amp;#34;inputs/events&amp;#34;) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT * FROM {{ events }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> WHERE event_name = &amp;#39;purchase&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% endwith %}&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">contract&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">is_append_only&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>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">is_event_stream&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>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">Only mark an ephemeral model as &lt;code>is_append_only: true&lt;/code> if all of its upstream inputs are also append-only &lt;strong>and&lt;/strong> the model&amp;rsquo;s SQL only filters or transforms without introducing mutations (no joins with mutable dimension tables, no aggregations that change with updates).&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="4-convert-entity-vars" data-heading="4: Convert entity vars" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="4-convert-entity-vars">4: Convert entity vars&lt;/h2>&lt;p>Add &lt;code>merge&lt;/code> clauses to entity vars to enable incremental computation. The &lt;code>merge&lt;/code> clause defines how to combine previous feature values with new calculations.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="choose-the-right-pattern" data-heading="Choose the right pattern" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="choose-the-right-pattern">Choose the right pattern&lt;/h3>&lt;p>Use the &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/" >Incremental Features&lt;/a> decision guide to determine which pattern applies:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Pattern&lt;/th>
&lt;th>When to use&lt;/th>
&lt;th>Reference&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Simple aggregation&lt;/td>
&lt;td>&lt;code>SUM&lt;/code>, &lt;code>MIN&lt;/code>, &lt;code>MAX&lt;/code>, &lt;code>COUNT&lt;/code>&lt;/td>
&lt;td>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Compound aggregation&lt;/td>
&lt;td>&lt;code>AVG&lt;/code>, &lt;code>WEIGHTED_AVG&lt;/code>, &lt;code>MIN_BY&lt;/code>/&lt;code>MAX_BY&lt;/code>, arrays, booleans&lt;/td>
&lt;td>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Incremental SQL model&lt;/td>
&lt;td>Stateful processing, rolling windows, multi-step logic&lt;/td>
&lt;td>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="quick-reference-common-migrations" data-heading="Quick reference: Common migrations" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="quick-reference-common-migrations">Quick reference: Common migrations&lt;/h3>&lt;p>&lt;strong>Simple aggregations&lt;/strong>: Add a matching &lt;code>merge&lt;/code>:&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">entity_var&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">first_purchase_time&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">min(timestamp)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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&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">entity_var&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">first_purchase_time&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{orders.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MIN({{rowset.first_purchase_time}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>Window functions&lt;/strong>: Replace with &lt;code>MAX_BY&lt;/code>/&lt;code>MIN_BY&lt;/code>:&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 (non-incremental window function)&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">entity_var&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">last_login_platform&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">last_value(platform)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/logins&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">window&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">order_by&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">timestamp&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 (incremental with MAX_BY + helper)&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">entity_var&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">last_login_platform&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{logins.platform}}, {{logins.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{rowset.last_login_platform}}, {{rowset.last_login_platform_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/logins&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">entity_var&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">last_login_platform_by_param&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{logins.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.last_login_platform_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/logins&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a> for the full &lt;code>MIN_BY&lt;/code>/&lt;code>MAX_BY&lt;/code> pattern and &lt;code>_by_param&lt;/code> helper documentation.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="when-merge-is-not-needed" data-heading="When merge is not needed" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="when-merge-is-not-needed">When merge is not needed&lt;/h3>&lt;p>Not every entity var requires a &lt;code>merge&lt;/code> clause:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;strong>Derived-only vars&lt;/strong> that reference other entity vars (no &lt;code>from&lt;/code> clause) are recomputed from their incrementally maintained dependencies:&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">entity_var&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">days_since_last_seen&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;DATEDIFF(day, {{user.last_seen}}, {{ end_time_sql }})&amp;#34;&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">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Days since the user was last seen&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Vars from window-bounded incremental tables&lt;/strong> that read from an incremental SQL model with a sliding window. The model already maintains state incrementally, and the var recomputes from the bounded window each run:&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">entity_var&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">active_days_in_past_7_days&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">count(distinct active_day)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/recent_active_days&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">active_day &amp;gt;= DATEADD(day, -7, {{ end_time_sql }})&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="eliminate-input-vars" data-heading="5: Eliminate input vars" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="eliminate-input-vars">5: Eliminate input vars&lt;/h2>&lt;p>Input vars scan all data on every run and block incremental processing. You must convert or replace every input var before the project can run incrementally.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="decision-tree" data-heading="Decision tree" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="decision-tree">Decision tree&lt;/h3>&lt;p>For each input var, follow this decision tree:&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">Input Var
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">+-- Can this logic be expressed as an entity var?
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-- Yes: Convert to entity_var with merge clause
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | (common for window functions like LAST_VALUE, FIRST_VALUE)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-- No
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| +-- Can the input var be replaced by a SQL model?
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | +-- Yes: Create a SQL model (possibly incremental) and
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | | reference it from entity vars
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | +-- No
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | +-- Create an incremental SQL model with full
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">| | DeRef pattern
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="example-convert-input-var-to-entity-var" data-heading="Example: Convert input var to entity var" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="example-convert-input-var-to-entity-var">Example: Convert input var to entity var&lt;/h3>&lt;p>This is the most common conversion. Window functions like &lt;code>LAST_VALUE&lt;/code> and &lt;code>FIRST_VALUE&lt;/code> can typically be replaced with &lt;code>MAX_BY&lt;/code> and &lt;code>MIN_BY&lt;/code>:&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 (input var with window function)&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">input_var&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">last_known_city&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">last_value(city)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">window&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">partition_by&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="nt">order_by&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">timestamp&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">city IS NOT NULL&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 (entity var with MAX_BY)&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">entity_var&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">last_known_city&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{events.city}}, {{events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX_BY({{rowset.last_known_city}}, {{rowset.last_known_city_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">events.city}} IS NOT NULL&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">entity_var&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">last_known_city_by_param&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{events.timestamp}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">MAX({{rowset.last_known_city_by_param}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/events&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>{{&lt;span class="l">events.city}} IS NOT NULL&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">is_feature&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&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-replace-input-var-with-incremental-sql-model" data-heading="Example: Replace input var with incremental SQL model" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="example-replace-input-var-with-incremental-sql-model">Example: Replace input var with incremental SQL model&lt;/h3>&lt;p>When input var logic is too complex for an entity var (multi-step transformations, complex joins), create an incremental SQL model:&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"># In sql_models.yaml&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">models&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">recent_active_days&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">model_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">sql_template&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">model_spec&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">occurred_at_col&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">timestamp&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">materialization&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">output_type&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">table&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">single_sql&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- set rootIncrementalPreReqs = this.RootIncrementalPreReqs() -%}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- set lastThis = this.DeRef(pre_existing=true, dependency=&amp;#34;optional&amp;#34;, checkpoint_name=&amp;#34;baseline&amp;#34;, prereqs=rootIncrementalPreReqs) -%}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% set events_delta = this.DeRef(&amp;#34;inputs/events/incr_delta_tbl&amp;#34;, dependency=&amp;#34;coercive&amp;#34;, baseline_name=&amp;#34;baseline&amp;#34;, prereqs=[lastThis]) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {% set events_full = this.DeRef(&amp;#34;inputs/events&amp;#34;, prereqs=[events_delta.Except()]) %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT user_id, active_day
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> FROM (
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- if lastThis.IsEnabled() %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT user_id, active_day FROM {{ lastThis }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> UNION ALL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT DISTINCT user_id, CAST(timestamp AS DATE) AS active_day
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> FROM {{ events_delta }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- else %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> SELECT DISTINCT user_id, CAST(timestamp AS DATE) AS active_day
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> FROM {{ events_full }}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> {%- endif %}
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> )
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> WHERE active_day &amp;gt;= DATEADD(&amp;#39;day&amp;#39;, -90, {{ end_time_sql }})&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">ids&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">select&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">type&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">entity&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">contract&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">is_append_only&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then reference the model from an entity var:&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">entity_var&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">active_days_last_30&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">COUNT(DISTINCT active_day)&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">models/recent_active_days&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">where&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">active_day &amp;gt;= DATEADD(&amp;#39;day&amp;#39;, -30, {{ end_time_sql }})&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="6-validate-with-rebase_incremental" data-heading="6: Validate with &lt;code>rebase_incremental&lt;/code>" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="6-validate-with-rebase_incremental">6: Validate with &lt;code>rebase_incremental&lt;/code>&lt;/h2>&lt;p>After completing the migration, validate that incremental results match full refresh results.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="validation-workflow" data-heading="Validation workflow" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h3 id="validation-workflow">Validation workflow&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Run a full refresh&lt;/strong> to establish a baseline:&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 run
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Run again&lt;/strong> to trigger incremental processing (if new data has arrived):&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 run
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Run with &lt;code>--rebase_incremental&lt;/code>&lt;/strong> to force a full rebuild and compare:&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 run --rebase_incremental
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;strong>Compare results&lt;/strong>: Verify that incremental and full refresh outputs match by comparing row counts, aggregated values, and spot-checking individual entities.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="checklist" data-heading="Checklist" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h4 id="checklist">Checklist&lt;/h4>&lt;ul>
&lt;li>&lt;strong>Row counts&lt;/strong>: Entity var tables should have the same number of rows&lt;/li>
&lt;li>&lt;strong>Value consistency&lt;/strong>: Feature values should match between incremental and full refresh runs&lt;/li>
&lt;li>&lt;strong>Performance&lt;/strong>: Incremental runs should be faster than the full refresh baseline (after the first run)&lt;/li>
&lt;li>&lt;strong>No errors&lt;/strong>: Check logs for warnings or errors related to incremental processing&lt;/li>
&lt;/ul>
&lt;blockquote class="warning">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/warning.svg alt="warning" loading="lazy" decoding="async" class="img__small" style="
margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">The first run after migration always performs a full refresh to establish the baseline checkpoint. Performance improvements are visible starting from the second run.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="migration-checklist" data-heading="Migration checklist" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="migration-checklist">Migration checklist&lt;/h2>&lt;p>This section contains a detailed migration checklist to convert your project to incremental mode.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="pre-migration" data-heading="Pre-migration" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h4 id="pre-migration">Pre-migration&lt;/h4>&lt;ul>
&lt;li>&lt;input disabled="" type="checkbox"> Inventory all inputs, SQL models, entity vars, and input vars&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Classify each input as append-only or mutable&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Verify append-only inputs with warehouse queries&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Identify all input vars that need conversion&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="during-migration" data-heading="During migration" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h4 id="during-migration">During migration&lt;/h4>&lt;ul>
&lt;li>&lt;input disabled="" type="checkbox"> Mark all append-only inputs with &lt;code>is_append_only: true&lt;/code> and &lt;code>occurred_at_col&lt;/code>&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Mark eligible ephemeral SQL models with &lt;code>is_append_only: true&lt;/code>&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Add &lt;code>merge&lt;/code> clauses to all entity vars that read from append-only sources&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Replace window functions with &lt;code>MAX_BY&lt;/code>/&lt;code>MIN_BY&lt;/code> patterns&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Convert or replace all input vars&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Create incremental SQL models for complex patterns&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Use &lt;code>{{ end_time_sql }}&lt;/code> instead of &lt;code>CURRENT_DATE&lt;/code> or &lt;code>CURRENT_TIMESTAMP()&lt;/code> in rolling-window filters&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="post-migration" data-heading="Post-migration" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h4 id="post-migration">Post-migration&lt;/h4>&lt;ul>
&lt;li>&lt;input disabled="" type="checkbox"> Run &lt;code>pb run&lt;/code> to establish baseline&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Run &lt;code>pb run&lt;/code> again to verify incremental processing&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Run &lt;code>pb run --rebase_incremental&lt;/code> and compare results&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Verify performance improvement on subsequent runs&lt;/li>
&lt;li>&lt;input disabled="" type="checkbox"> Remove any unused input vars or deprecated models&lt;/li>
&lt;/ul>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="common-pitfalls" data-heading="Common pitfalls" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="common-pitfalls">Common pitfalls&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Pitfall&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Missing &lt;code>merge&lt;/code> clause&lt;/td>
&lt;td>Entity vars without &lt;code>merge&lt;/code> cannot run incrementally&lt;/td>
&lt;td>Add appropriate &lt;code>merge&lt;/code> clause matching the &lt;code>select&lt;/code> aggregation&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Incorrect merge function&lt;/td>
&lt;td>Using &lt;code>COUNT&lt;/code> instead of &lt;code>SUM&lt;/code> for count merges&lt;/td>
&lt;td>For &lt;code>COUNT(...)&lt;/code> in &lt;code>select&lt;/code>, use &lt;code>SUM({{rowset.feature}})&lt;/code> in &lt;code>merge&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Missing &lt;code>_by_param&lt;/code> helper&lt;/td>
&lt;td>Using &lt;code>MAX_BY&lt;/code>/&lt;code>MIN_BY&lt;/code> without the ordering companion var&lt;/td>
&lt;td>Always define a &lt;code>_by_param&lt;/code> helper var with &lt;code>is_feature: false&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Mutable input marked append-only&lt;/td>
&lt;td>Dimension table incorrectly marked as &lt;code>is_append_only: true&lt;/code>&lt;/td>
&lt;td>Verify append-only behavior before marking; dimension tables should NOT be append-only&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Using &lt;code>CURRENT_DATE&lt;/code> in filters&lt;/td>
&lt;td>Non-deterministic results across re-runs&lt;/td>
&lt;td>Use &lt;code>{{ end_time_sql }}&lt;/code> instead&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Input vars still present&lt;/td>
&lt;td>Input vars block incremental processing&lt;/td>
&lt;td>Convert to entity vars or incremental SQL models&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Non-composable merge function&lt;/td>
&lt;td>Using &lt;code>AVG&lt;/code> directly in &lt;code>merge&lt;/code>&lt;/td>
&lt;td>Decompose into &lt;code>SUM&lt;/code>/&lt;code>COUNT&lt;/code> components via &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="see-more" data-heading="See more" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/migrate-project-to-incremental/" data-title="How to Migrate a Project to Incremental" -->
&lt;h2 id="see-more">See more&lt;/h2>&lt;ul>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" >How to Make Features Incremental&lt;/a>: Feature-level migration guide&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/" >Incremental Features&lt;/a>: Pattern selection guide&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/simple-aggregations/" >Simple Aggregations&lt;/a>: SUM, MIN, MAX, COUNT patterns&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/compound-aggregations/" >Compound Aggregations&lt;/a>: AVG, MIN_BY/MAX_BY, array, boolean patterns&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>: Stateful processing patterns&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/profiles-yaml/var-groups/input-var/" >Input Var&lt;/a>: Input var reference and migration guidance&lt;/li>
&lt;/ul></description></item><item><title>Archive: How to Use Checkpoints</title><link>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/</guid><description>
&lt;p>This guide explains how to reference and use checkpoints when building incremental features and SQL models.&lt;/p>
&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/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="overview">Overview&lt;/h2>&lt;p>Checkpoints represent point-in-time snapshots of warehouse data and their computed outputs from previous runs, enabling incremental computation. How you reference checkpoints depends on whether you&amp;rsquo;re using incremental entity vars or incremental SQL models.&lt;/p>
&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a> for conceptual information.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="usage-with-incremental-entity-vars" data-heading="Usage with incremental entity vars" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="usage-with-incremental-entity-vars">Usage with incremental entity vars&lt;/h2>&lt;p>When using a &lt;code>merge:&lt;/code> clause in an incremental entity var, Profiles uses the checkpoint implicitly. You don&amp;rsquo;t need to explicitly reference the checkpoint.&lt;/p>
&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/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h3 id="example">Example&lt;/h3>&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">entity_var&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">total_purchases&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">select&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{orders.value}})&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">merge&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">SUM({{rowset.total_purchases}})&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">from&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">inputs/orders&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="how-it-works" data-heading="How it works" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h3 id="how-it-works">How it works&lt;/h3>&lt;p>The &lt;code>{{rowset.total_purchases}}&lt;/code> reference automatically pulls the value from the baseline checkpoint. Profiles:&lt;/p>
&lt;ul>
&lt;li>Retrieves the previously computed value from the baseline checkpoint&lt;/li>
&lt;li>Computes the delta (new rows since the baseline)&lt;/li>
&lt;li>Merges them using the &lt;code>merge&lt;/code> property&lt;/li>
&lt;/ul>
&lt;p>The &lt;code>{{rowset.}}&lt;/code> syntax refers to the changed rowset from the baseline checkpoint, giving you access to previous checkpoint values during the merge operation.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="usage-with-incremental-sql-models" data-heading="Usage with incremental SQL models" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="usage-with-incremental-sql-models">Usage with incremental SQL models&lt;/h2>&lt;p>When building an incremental SQL model, you must reference the previous checkpoint &lt;strong>explicitly&lt;/strong> using &lt;code>this.DeRef()&lt;/code> with &lt;code>pre_existing=true&lt;/code>.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="reference-past-version-of-current-model" data-heading="Reference past version of current model" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h4 id="reference-past-version-of-current-model">Reference past version of current model&lt;/h4>&lt;p>To reference the previous materialization of the current model:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">%-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">rootIncrementalPreReqs&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">RootIncrementalPreReqs&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">checkpoint_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">prereqs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">rootIncrementalPreReqs&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">All&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">before&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Note&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">that&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">should&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">not&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">be&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">put&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">conditionals&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">mark&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependencies&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">—&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">prereqs&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">conditional&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependencies&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">IsEnabled&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="c1">-- Incremental mode: merge with baseline
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">}}&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="k">UNION&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">ALL&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="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">}}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="c1">-- Full refresh mode: process all data
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inputs/events&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">}}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">endif&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="reference-another-models-previous-materialization" data-heading="Reference another model&amp;rsquo;s previous materialization" data-level="4" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h4 id="reference-another-models-previous-materialization">Reference another model&amp;rsquo;s previous materialization&lt;/h4>&lt;p>To reference another model&amp;rsquo;s previous materialization:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">%-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">rootIncrementalPreReqs&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">RootIncrementalPreReqs&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">previousModel&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;models/previous_model&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">prereqs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">rootIncrementalPreReqs&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-%&lt;/span>&lt;span class="err">}&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="key-points" data-heading="Key points" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h3 id="key-points">Key points&lt;/h3>&lt;ul>
&lt;li>Use &lt;code>pre_existing=true&lt;/code> to reference previous materializations. This indicates that the referenced material will NOT be created in the current run. If it doesn&amp;rsquo;t exist, it will be disabled. In SQL templates, you can check if the material is enabled using &lt;code>&amp;lt;material&amp;gt;.IsEnabled()&lt;/code>.&lt;/li>
&lt;li>Use &lt;code>dependency=&amp;quot;optional&amp;quot;&lt;/code> to handle cases where no baseline exists&lt;/li>
&lt;li>Always check if &lt;code>&amp;lt;reference&amp;gt;.IsEnabled()&lt;/code> is true/false to support full refresh mode (when baseline doesn&amp;rsquo;t exist, &lt;code>IsEnabled()&lt;/code> returns false)&lt;/li>
&lt;li>Use &lt;code>checkpoint_name&lt;/code> to specify which baseline to use (defaults to &lt;code>&amp;quot;baseline&amp;quot;&lt;/code>)&lt;/li>
&lt;/ul>
&lt;p>See &lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/deref-reference/" >DeRef Reference&lt;/a> for complete syntax and usage.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="delta-models" data-heading="Delta models" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="delta-models">Delta models&lt;/h2>&lt;p>Profiles automatically creates delta models for append-only inputs at the path &lt;code>/path/to/input/incr_delta_tbl&lt;/code>. These models contain only rows that arrived after the baseline checkpoint timestamp.&lt;/p>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="reference-delta-models" data-heading="Reference delta models" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h3 id="reference-delta-models">Reference delta models&lt;/h3>&lt;p>Reference delta models in your incremental SQL templates:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="err">{&lt;/span>&lt;span class="o">%-&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&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="n">pre_existing&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">true&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="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;optional&amp;#34;&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="n">checkpoint_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inputs/events/incr_delta_tbl&amp;#34;&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="n">dependency&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;coercive&amp;#34;&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="n">baseline_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;baseline&amp;#34;&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="n">prereqs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="p">])&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">set&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_full&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;inputs/events&amp;#34;&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="n">prereqs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="k">Except&lt;/span>&lt;span class="p">()])&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">All&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">before&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">this&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Note&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">that&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">should&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">not&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">be&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">put&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">conditionals&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DeRef&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">mark&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependencies&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">—&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">prereqs&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">conditional&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">dependencies&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">#&lt;/span>&lt;span class="err">}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">lastThis&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">IsEnabled&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="c1">-- Incremental mode: use delta
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_delta&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">}}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="c1">-- Full refresh mode: use full input
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">{{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">events_full&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="err">}}&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="err">{&lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">endif&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">%&lt;/span>&lt;span class="err">}&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="how-delta-models-work" data-heading="How delta models work" data-level="3" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h3 id="how-delta-models-work">How delta models work&lt;/h3>&lt;ul>
&lt;li>Delta models contain only rows that arrived after the baseline checkpoint timestamp&lt;/li>
&lt;li>They&amp;rsquo;re automatically enabled when a baseline exists, disabled otherwise&lt;/li>
&lt;li>Use &lt;code>prereqs=[lastThis]&lt;/code> to ensure the delta model is created only when a baseline exists&lt;/li>
&lt;li>Use &lt;code>baseline_name&lt;/code> to specify which baseline to use for delta computation (must match &lt;code>checkpoint_name&lt;/code>)&lt;/li>
&lt;/ul>
&lt;!DOCTYPE html>
&lt;html lang="en">
&lt;blockquote class="tip">
&lt;div class="tip-quote">
&lt;img src=https://www.rudderstack.com/docs/docs/images/tip.svg loading="lazy" alt="tip" decoding="async" class="img__small" style="margin-top: 3px; width: 20px;height: 16px;" />
&lt;div class="tip-text">&lt;strong>Tip:&lt;/strong>
Always declare all DeRefs together at the top of your template, not inside conditionals. Use &lt;code>prereqs&lt;/code> to chain conditional evaluation instead.&lt;/div>
&lt;/div>
&lt;/blockquote>
&lt;/html>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="checkpoint-management" data-heading="Checkpoint management" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="checkpoint-management">Checkpoint management&lt;/h2>&lt;p>Profiles automatically creates checkpoints after each successful run. Each checkpoint is identified by a sequence number and associated with specific time boundaries. Model output tables reference their checkpoint through their materialized table names (e.g., &lt;code>Material_&amp;lt;modelname&amp;gt;_&amp;lt;modelhash&amp;gt;_&amp;lt;checkpoint_seqno&amp;gt;&lt;/code>).&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/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="troubleshooting">Troubleshooting&lt;/h2>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Issue&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>No baseline checkpoint available&lt;/td>
&lt;td>Profiles automatically performs a full refresh to create the baseline. Ensure regular runs to maintain baseline availability.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Baseline checkpoint incompatible&lt;/td>
&lt;td>When new entity vars are added or existing definitions change, Profiles automatically discovers the model hash change and runs a full refresh.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Checkpoints are too old&lt;/td>
&lt;td>Profiles can use older checkpoints, but performance may degrade. Maintain regular run schedules.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Materials consume excessive storage&lt;/td>
&lt;td>Profiles automatically cleans up old materials based on your model retention periods. Review retention settings to adjust cleanup behavior.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>pre_existing=true&lt;/code> returns &lt;code>nil&lt;/code>&lt;/td>
&lt;td>This is expected on first run or when no baseline exists. Always handle this case with conditional logic for full refresh mode.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Delta model not available&lt;/td>
&lt;td>Ensure your input has &lt;code>contract: is_append_only: true&lt;/code> configured. Delta models are only created for append-only inputs.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- end-chunk -->
&lt;!-- begin-chunk data-anchor="see-more" data-heading="See more" data-level="2" data-permalink="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/use-checkpoints/" data-title="How to Use Checkpoints" -->
&lt;h2 id="see-more">See more&lt;/h2>&lt;ul>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/concepts/incremental-features/checkpoints-and-baselines/" >Checkpoints and Baselines&lt;/a>: Conceptual overview&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/" >Incremental SQL Models&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/incremental-sql-models/deref-reference/" >DeRef Reference&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.rudderstack.com/docs/archive/profiles/0.25/dev-docs/incremental-features/make-features-incremental/" >How to Make Features Incremental&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>