<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
  <title>Altimate AI Blog</title>
  <link>https://altimate.ai/blog</link>
  <atom:link href="https://altimate.ai/blog.rss.xml" rel="self" type="application/rss+xml" />
  <description>Insights on AI agents, data engineering, Snowflake, dbt, and analytics.</description>
  <language>en-us</language>
  <ttl>60</ttl>
  <image>
    <url>https://altimate.ai/logo512.png</url>
    <title>Altimate AI Blog</title>
    <link>https://altimate.ai/blog</link>
  </image>
  <lastBuildDate>Fri, 24 Jul 2026 17:50:43 GMT</lastBuildDate>
  <item>
    <title>Why AI Agents Break in Production: The Missing Harness in Your Data Stack</title>
    <link>https://altimate.ai/blog/why-ai-agents-break-in-production-the-missing-harness-in-your-data-stack</link>
    <guid isPermaLink="true">https://altimate.ai/blog/why-ai-agents-break-in-production-the-missing-harness-in-your-data-stack</guid>
    <pubDate>Wed, 15 Jul 2026 18:50:14 GMT</pubDate>
    <dc:creator>Pradnesh Patil</dc:creator>
    <category>Data Science</category>
    <category>data-engineering</category>
    <category>AI</category>
    <description>Listen to the full conversation on DataScienceWithSam, available on Apple Podcasts and Spotify.
Most data teams have lived some version of this same story: an AI agent runs a query, the query returns</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/why-ai-agents-break-in-production-the-missing-harness-in-your-data-stack/80136cc1-556c-41ad-8d5b-a914072837a2.jpg" alt="Why AI Agents Break in Production: The Missing Harness in Your Data Stack" /></p>
<p><em>Listen to the full conversation on DataScienceWithSam, available on</em> <a href="https://podcasts.apple.com/us/podcast/ep-45-why-ai-agents-break-in-production-the-missing/id1587954336?i=1000776852944"><em>Apple Podcasts</em></a> <em>and</em> <a href="https://open.spotify.com/episode/0nKtoDZCNpcgD2NOAyFVzO?si=Vzos9X0YTkSeS0bUXoF9Mw&amp;nd=1&amp;dlsi=3d298d39cd99420e"><em>Spotify</em></a>.</p>
<p>Most data teams have lived some version of this same story: an AI agent runs a query, the query returns a result, the number looks reasonable, and the dashboard ships. Weeks later, someone traces a bad decision back to that query and finds a join that never should have executed the way it did. Nobody caught it in the moment because nothing about the failure looked like a failure.</p>
<p>On this episode of DataScienceWithSam, Pradnesh Patil, Co-Founder and CEO of Altimate AI argues that this is not a symptom of weak models. It is the predictable result of asking an agent to act without the infrastructure required to know what is true about the data. The gap is not in what the model can do, it is in what the model has been given to work with.</p>
<p><strong>The core distinction: prompts vs. harnesses</strong></p>
<p>A system prompt tells a model what to do. A harness tells it what is actually true. That distinction, Patil says, is the one most teams get wrong when their first AI data agent rollout stalls out or quietly produces bad numbers. Teams write increasingly elaborate instructions into the prompt, hoping better wording will compensate for the model having no grounded view of the schema, the lineage, or the cost of the action it is about to take. It rarely does.</p>
<p>Patil breaks the agentic data engineering harness into five components: context, governance, MCP tools, shared skills, and agent infrastructure. Each one answers a different question an agent needs answered before it acts responsibly. Context tells the agent what the data actually looks like today. Governance tells it what it is allowed to do. Tools give it the concrete means to act. Shared skills capture the institutional knowledge a team has already built up. Agent infrastructure ties all of it together into something that runs reliably at scale.</p>
<p>Miss any single one of those five components, Patil says, and the resulting failures are silent. The query runs, it returns a result, maybe the result looks correct to any human checking... but it is not, and nothing in the interface tells anyone that until the damage has already spread downstream into a report, a model, or a decision.</p>
<p>Between 27% and 33% of AI-generated queries reference tables that do not exist in the schema, phantom references that a grounded agent would never produce in the first place. A further 78% contain what Patil calls "silent wrong joins": joins that execute cleanly, return a syntactically valid result, and still return the wrong data. Neither statistic describes a model that is bad at SQL. Both describe what happens in the absence of infrastructure that keeps a model grounded in the real, current state of the data it is querying.</p>
<p><strong>Harness beats model size</strong></p>
<p>The instinct when an agent underperforms is to reach for a bigger model. Patil pushes back on that instinct directly, and points to <a href="https://altimate.ai/products/altimate-code">Altimate Code</a>'s performance on ADE-Bench as the clearest evidence against it. Altimate Code topped the leaderboard running on Sonnet, while competing systems relied on Opus, a materially larger and more expensive model, to reach lower scores.</p>
<p>The takeaway is not that a smaller model can outperform a larger one under identical conditions, but that the system surrounding the model, the harness that grounds it in context and governs what it is allowed to do, determines outcomes more than raw model capability does. For data teams evaluating where to invest, that reframes the question. The more valuable investment is often not the next model upgrade. It is the infrastructure that makes any model reliable once it is put to work on real data.</p>
<p><strong>Where LLMs should, and shouldn't, make decisions</strong></p>
<p>A recurring theme here is the boundary between deterministic and probabilistic reasoning. Validation, cost checks, and query correctness are deterministic problems, Patil argues: they have a right answer that does not depend on interpretation, and they should never be handed to a model to reason about probabilistically. A query either references a table that exists or it does not. A join either matches the keys correctly or it does not. A cost estimate either falls inside budget or it does not. None of that needs a language model's judgment.</p>
<p>Hard rules should handle hard rules, and the model's judgment should be reserved for genuine ambiguity, the calls that actually require weighing context and making a reasoned choice. Building a harness that respects this boundary, rather than routing everything through the model, is what keeps an agent from confidently producing a wrong answer with the same tone of voice it uses for a right one.</p>
<p><strong>Fixing context compaction for long-running tasks</strong></p>
<p>Standard LLM context compaction was designed for general-purpose chat, where discarding older turns of a conversation carries little cost. Applied to a long-running data engineering task, the same compaction approach tends to discard exactly the schema and lineage context an agent needs to keep working correctly. An agent that loses that context mid-task does not usually stop. It keeps going, with a thinner and thinner grip on what is actually true, until its output drifts from correct to merely plausible.</p>
<p>Altimate's response is a compaction approach built specifically for this kind of task, one that treats schema and lineage as context to be preserved rather than as expendable conversational history. The distinction matters most on the tasks that take the longest: multi-step pipeline builds, large-scale migrations, and anything else where an agent is expected to stay grounded over many turns rather than a handful.</p>
<p><strong>The $5,000 query bill</strong></p>
<p>Governance is not an abstract concern here. Patil cites a real $5,000 Cortex AI query bill as the kind of outcome that permission-based governance helps avoid. The bill was not the result of malicious intent or a rare edge case. It was the predictable outcome of an agent operating without limits on what it was allowed to query and at what cost.</p>
<p>Without <a href="https://altimate.ai/use-cases/altimate-for-snowflake"><strong>controls on scope and spend</strong></a>, Patil argues, agents can go rogue on cloud cost just as easily as they can go rogue on correctness, and the two failure modes compound each other. An ungoverned agent that is also ungrounded in the real schema is not just likely to produce a wrong answer. It is likely to produce a wrong and expensive answer, executed against the wrong tables, at a cost nobody approved in advance.</p>
<p><strong>Where data engineering is headed</strong></p>
<p>Patil's broader claim is that the era of hand-writing SQL is ending. The role is shifting toward building and governing the systems that let agents do that work reliably: defining the context that grounds them, the governance that constrains them, and the shared skills that let institutional knowledge outlive any one person's tenure on a team.</p>
<p>His advice reflects that same emphasis on infrastructure over individual features: Build open source, build cross-platform, so that the tools work across Snowflake, Databricks, and every other environment your data estate actually spans. Avoid siloed AI features that solve a narrow problem for one vendor's users without moving the broader field forward. For Patil, the teams that internalize this shift early, and start investing in the harness rather than the next model swap, are the ones that will find AI agents genuinely trustworthy in production, rather than merely fast and occasionally, silently, wrong.</p>
<p><em>Listen to the full conversation on DataScienceWithSam, available on</em> <a href="https://podcasts.apple.com/us/podcast/ep-45-why-ai-agents-break-in-production-the-missing/id1587954336?i=1000776852944"><em>Apple Podcasts</em></a> <em>and</em> <a href="https://open.spotify.com/episode/0nKtoDZCNpcgD2NOAyFVzO?si=Vzos9X0YTkSeS0bUXoF9Mw&amp;nd=1&amp;dlsi=3d298d39cd99420e"><em>Spotify</em></a>.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/why-ai-agents-break-in-production-the-missing-harness-in-your-data-stack/80136cc1-556c-41ad-8d5b-a914072837a2.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>4 Blind Spots of General Coding Agents in Data Engineering</title>
    <link>https://altimate.ai/blog/4-blind-spots-of-general-coding-agents-in-data-engineering</link>
    <guid isPermaLink="true">https://altimate.ai/blog/4-blind-spots-of-general-coding-agents-in-data-engineering</guid>
    <pubDate>Mon, 06 Jul 2026 22:35:27 GMT</pubDate>
    <dc:creator>Syed Haider</dc:creator>
    <category>data-engineering</category>
    <category>AI</category>
    <category>llm</category>
    <category>ai agents</category>
    <category>SQL</category>
    <description>A coding agent enters the data warehouse
A data engineer drops a one-liner into Claude Code: &quot;Add patient_visit_count to dim_patient.&quot; Twenty seconds later, Claude has read the project, scanned source</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/cb2766a9-9af9-4ce0-9fea-1c78181cc938.jpg" alt="4 Blind Spots of General Coding Agents in Data Engineering" /></p>
<h2><strong>A coding agent enters the data warehouse</strong></h2>
<p>A data engineer drops a one-liner into Claude Code: <em>"Add</em> <code>patient_visit_count</code> <em>to</em> <code>dim_patient</code><em>."</em> Twenty seconds later, Claude has read the project, scanned <code>sources.yml</code>, and written plausible-looking SQL. <code>dbt compile</code> is happy. The PR merges Friday evening.</p>
<p>At 2 AM Saturday, the scheduled job fires. The model references <code>PATIENT_ID</code>, but the actual warehouse column is <code>SUBJECT_ID</code>. The run fails in production.</p>
<p>Nothing about the SQL looked obviously wrong. Claude inferred the schema from surrounding code and naming patterns instead of verifying it against the actual warehouse.</p>
<p>Claude Code can write a dbt model. What it can't do, by itself, is run that SQL against your warehouse before you ship it.</p>
<p>This is one instance of a broader pattern. General coding agents like Claude, Cursor, and Copilot are designed for software where the source code <em>is</em> the truth. Data engineering inverts that: the <em>warehouse</em> is the truth, dbt YAML is its description, the agent's SQL is a guess. When the warehouse and the code disagree, only the warehouse is right, and the agent has no way to ask.</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/046ef1d7-41df-4e4b-9f6b-a1ad127fab6b.svg" alt="" style="display:block;margin:0 auto" />

<p>This isn't a hypothetical. In our first experiment, bare Claude shipped a dbt model with <strong>two hallucinated column names</strong> that looked right based on the surrounding code but didn't exist in the actual Snowflake table. <code>dbt compile</code> passed. The model would have failed on first real run.</p>
<p>The altimate-code plugin catches this because Claude calls it before generating, and it actually queries the warehouse for the real columns.</p>
<blockquote>
<p>The altimate plugin gives Claude warehouse hands: schema introspection, cross-warehouse execution, dbt-idiomatic defaults. That's what turns a code generator into something that finishes the task.</p>
</blockquote>
<p>We ran three categorically different experiments to find out where this matters and where it doesn't. The answer is more interesting than "always" or "never.", and reveals four common blind spots when deploying coding agents on data engineering tasks.</p>
<hr />
<h2><strong>The three experiments</strong></h2>
<p>We deliberately picked task shapes that stress different parts of an AI data engineering workflow:</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/abcd9081-66dc-4639-9360-1dc55c645e27.svg" alt="" style="display:block;margin:0 auto" />

<p>Each task answers a different question about where the plugin actually earns its keep. Taken together, they give you a framework to predict where it'll pay off on <em>your</em> workloads.</p>
<hr />
<h2><strong>Blind spot #1: Schema hallucination on real warehouses</strong></h2>
<p><strong>The task:</strong> A real Snowflake mart-layer refactor of a patient-360 model with HIPAA constraints, and dozens of column-level decisions.</p>
<p><strong>What happened bare:</strong> Claude generated a working-looking model. Two column names were inferred from context, close to right but wrong. <code>dbt compile</code> was happy. Code review by a human would likely have missed them (they looked plausible).</p>
<p><strong>What happened with the plugin:</strong> Claude delegated schema introspection to <a href="https://www.altimate.ai/products/altimate-code">altimate-code</a>'s <code>altimate-dbt columns</code> tool, which hit Snowflake directly and returned the actual columns. The hallucinated names were caught before generation.</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/e2c47f6d-9514-470d-9145-0e9ba811af41.svg" alt="" style="display:block;margin:0 auto" />

<p><strong>The cost was a wash.</strong> Plugin runs landed at near-parity per-token spend. So the correctness win is essentially free for any real-warehouse work.</p>
<blockquote>
<p><em>If your Claude is touching real warehouse models, the (free) plugin pays for itself by not shipping broken column names.</em></p>
</blockquote>
<hr />
<h2>Blind spot #2: Cross-warehouse work the agent can't reach</h2>
<p><strong>The task.</strong> Migrate a customer's project from MSSQL to Snowflake. Validate parity. This requires connecting to <em>both</em> warehouses, reading from one, comparing aggregates to the other.</p>
<p><strong>What happened bare.</strong> Five attempts in a row, Claude crashed on the connectivity layer. No <code>pyodbc</code> driver. No <code>pymssql</code>. No idea how to find MSSQL credentials. <strong>Five runs produced zero working output.</strong></p>
<p><strong>What happened with the plugin.</strong> altimate-code's pre-baked warehouse adapters drove the cross-DB diff end-to-end across four internal sub-sessions, with 9+ real <code>pyodbc.connect()</code> calls and a working parity report at the end.</p>
<p><strong>The honest cost:</strong> ~6× a bare-Claude run. But bare-Claude's run produced <em>nothing</em>. The right comparison isn't dollars-per-attempt, it's <strong>dollars-per-correct-answer</strong>, and bare-Claude's denominator is zero.</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/07f49cc0-9dcb-47a8-a3c9-df1dba8557cf.svg" alt="" style="display:block;margin:0 auto" />

<blockquote>
<p><em>For cross-warehouse migrations, parity work, or source-of-truth reconciliation, the plugin isn't a nice-to-have. It's the only path that finishes.</em></p>
</blockquote>
<hr />
<h2>Blind spot #3: Default SQL patterns aren't dbt-idiomatic</h2>
<p>This was the surprise.</p>
<p><strong>The benchmark.</strong> ADE-Bench: 24 dbt tasks running against local DuckDB, objectively scored. Crucially, Claude has <em>everything it needs locally</em>: no cross-warehouse, no missing drivers. This is the "where the plugin shouldn't matter" scenario.</p>
<p><strong>The headline result.</strong> Of 5 hard tasks bare Claude failed, the plugin's <em>passive presence</em> (just being installed; no Skill tool invocation, no subprocess delegation) <strong>rescued 1</strong>. Specifically: an ADE-Bench task called <code>intercom003</code> went from FAIL → PASS for an extra ~$0.13 in tokens.</p>
<p>Here's what changed in the output:</p>
<table>
<thead>
<tr>
<th>Operation</th>
<th>Bare Claude (FAIL)</th>
<th>With plugin loaded (PASS)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Removing duplicate rows</strong></td>
<td>implicit join, missed dupes</td>
<td><code>QUALIFY ROW_NUMBER() OVER (...)</code></td>
</tr>
<tr>
<td><strong>Handling missing values</strong></td>
<td>"empty values expected"</td>
<td><code>COALESCE(..., 0)</code> everywhere</td>
</tr>
<tr>
<td><strong>Computing time differences</strong></td>
<td><code>date_diff('second', ...)</code></td>
<td><code>EXTRACT(EPOCH FROM ...) / 60</code></td>
</tr>
</tbody></table>
<p>Bare Claude defended its wrong output as expected behavior. Plugin Claude wrote dbt-idiomatic SQL. <strong>The Skill tool never fired.</strong> The plugin's value here was purely the loaded skill descriptions sitting in Claude's context, biasing it toward correct patterns.</p>
<p>And the <code>intercom003</code> task wasn't the only one we ran. We tested the full 5 hard ADE-Bench tasks across 4 configurations (passive, forced consultation, mandatory delegation) to map which mechanisms actually flipped failures:</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/4513c380-0457-49f8-92ca-97183ad9ea6f.svg" alt="" style="display:block;margin:0 auto" />

<p>Two rescues, two completely different mechanisms. The <strong>passive presence</strong> rescue (<code>intercom003</code>) was nearly free. The <strong>mandatory delegation</strong> rescue (another ADE-Bench task, <code>analytics_engineering006</code>) cost 18× a bare run but turned 0/7 tests into 7/7. Forcing the Skill tool to fire without demanding actual delegation rescued nothing. Claude reads the guidance, then proceeds to do the work itself.</p>
<blockquote>
<p><em>Even if Claude never delegates to altimate-code, the plugin's presence is a free correctness prior on dbt-shaped code.</em></p>
</blockquote>
<p>The cheapest mode of adoption (just enable the plugin and walk away) measurably improves dbt output quality.</p>
<hr />
<h2><strong>Blind spot #4: Wasted exploration on tasks the agent could solve</strong></h2>
<p><em>The first three blind spots are about things Claude can't do at all without the plugin. This one is different: it's about tasks Claude can already solve and whether the plugin makes those cheaper or more expensive. The answer is surprising: just having the plugin loaded changes how Claude explores, even when no plugin tools ever fire.</em></p>
<p>The <code>intercom003</code> task rescue hinted at something deeper than tool augmentation: the plugin was changing Claude's <em>search behavior</em> even when no plugin tools fired. So we asked whether that same passive context bias also reduced cost on tasks Claude <em>already</em> solved correctly.</p>
<p>We replayed three ADE-Bench medium tasks where bare Claude already produced correct, test-passing answers (<code>f1006</code> semantic data fix, <code>f1010</code> analysis gotchas, <code>airbnb009</code> missing-days debug), this time with the plugin enabled. Both configurations passed all tests. We compared turns, tool calls, and spend.</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/8ff9a3a9-5e6b-45af-ae0d-ceb483cb62d1.svg" alt="" style="display:block;margin:0 auto" />

<p><em>(Note:</em> <code>airbnb009</code> <em>above is a medium-complexity task, and different from</em> <code>airbnb005</code><em>-shape, the simpler task class discussed in the next section of this article.)</em></p>
<p><strong>The aggregate is a 18.6% cost reduction with the plugin enabled, on tasks where both produce identical, correct outputs.</strong> Two of three tasks were cheaper with the plugin; one was essentially flat. The biggest win, <code>f1006</code>, saw the plugin use <strong>4 fewer turns and 15 fewer tool calls</strong> than bare.</p>
<p>Importantly, this isn't from the plugin's deterministic tools firing. In all three runs, <code>altimate-dbt</code> <strong>was never invoked</strong>. Claude used the same Read/Bash/Edit tools either way. The savings come from the skill descriptions in Claude's system prompt biasing exploration: plugin Claude reads fewer files, skips more dead-end debugging paths, converges to the answer with less noise.</p>
<blockquote>
<p><em>Loaded plugin context is a prior, not a tax. It guides exploration toward the answer, even when the bundled tools never fire.</em></p>
</blockquote>
<p>This generalizes the <code>intercom003</code> task result: passive context bias improves both correctness <em>and</em> efficiency on real dbt work.</p>
<hr />
<h2><strong>The decision framework</strong></h2>
<p>Here's a single chart you can use to decide, task by task, which mode of the plugin matters and what it'll cost:</p>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/2749eba5-d74e-49cd-a8ea-29e81fe52acb.svg" alt="" style="display:block;margin:0 auto" />

<p>Use this to predict where the plugin will pay off on <em>your</em> workloads.</p>
<hr />
<h2><strong>Where the plugin doesn't help</strong></h2>
<p>It's not a free lunch everywhere. Two patterns to know about before you adopt:</p>
<ul>
<li><p><strong>On the simplest model-creation tasks (</strong><code>airbnb005</code><strong>-shape), plugin presence costs +25%</strong> with no correctness gain. These are tasks bare Claude one-shots in a handful of turns; there's no exploration loop for the context bias to short-circuit. On a richer mix of dbt mediums (Blind spot #4) the aggregate flipped the other way to −18.6%, but the simplest end of the spectrum is a small tax.</p>
</li>
<li><p><strong>The Skill tool is advisory, not delegating.</strong> Even forcing it to "fire" via system-prompt nudges doesn't translate to Claude actually executing altimate-code. We tested this. Don't over-invest in prompt tricks. Just install the plugin and let the passive context bias do the work, then <em>prompt invoke</em> altimate-code for cross-warehouse tasks.</p>
</li>
</ul>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/51c65e79-7ab7-47f7-9792-2980ac5ff00c.svg" alt="" style="display:block;margin:0 auto" />

<p>The pattern is consistent: <strong>the plugin shines on the work that's actually hard</strong>. For trivial tasks, it's a small tax. For warehouse-shaped, multi-DB, or idiom-sensitive work, it's the difference between a working answer and no answer.</p>
<p><strong>Recommendation:</strong> Leave the plugin on by default. The +25% overhead on trivial tasks is small in absolute terms (these are cheap, short runs), and dynamically toggling introduces friction that costs more in engineering time than it saves in tokens. The aggregate across a realistic mixed workload still favors leaving it enabled. If you're running a batch of pure staging model scaffolding with no warehouse lookups, that's the one case worth disabling it — but it's the exception, not the workflow to optimize for.</p>
<hr />
<h2><strong>How to adopt: — the 5-minute path</strong></h2>
<img src="/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/11421822-6d14-436a-98ba-4e7ed39e488f.svg" alt="" style="display:block;margin:0 auto" />

<p><strong>Step 1.</strong> Add to <code>~/.claude/settings.json</code>:</p>
<pre><code class="language-json">{
  "enabledPlugins": {
    "data-engineering-skills": true
  }
}
</code></pre>
<p><strong>Step 2.</strong> Verify it loaded:</p>
<pre><code class="language-bash">claude --print "list available skills" | grep -i altimate
</code></pre>
<p><strong>Step 3.</strong> For cross-warehouse and parity tasks, demand altimate-code explicitly in the prompt:</p>
<pre><code class="language-plaintext">Use altimate-code to drive the cross-DB diff
</code></pre>
<p><strong>Step 4.</strong> Pre-bake your warehouse credentials in altimate-code's connection registry once. Saves re-doing it per task and avoids credential leakage into prompts.</p>
<hr />
<h2><strong>The bottom line</strong></h2>
<p>The altimate plugin doesn't make Claude smarter at SQL. It makes Claude <strong>competent at the parts of data engineering that aren't SQL</strong>: schema introspection, cross-warehouse connectivity, dbt-idiomatic defaults. And on the dbt work it already could do, it does it with fewer tokens.</p>
<p>For data teams running Claude on real warehouse work, that's the difference between a code generator and an agent that finishes the task.</p>
<blockquote>
<p><em>Bare Claude is cheap when it works. When it doesn't (when the warehouse can't be reached, or when the column names are wrong), the cost is undefined. And even when it does work, plugin Claude usually gets there cheaper.</em></p>
</blockquote>
<hr />
<p><strong>Try it.</strong> <a href="https://github.com/AltimateAI/data-engineering-skills">Altimate Data Engineering Skills Plugin for Claude Code</a></p>
<p>If you run it on your next migration or parity task, we'd love to hear what shape of work it helped, or didn't.</p>
<hr />
<p><em>All three experiments used Claude Sonnet 4.6 uniformly. Sample size is small per task (1-2 runs per configuration); the task shapes are deliberately divergent, so treat the numbers as directional rather than precise.</em></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/4-blind-spots-of-general-coding-agents-in-data-engineering/cb2766a9-9af9-4ce0-9fea-1c78181cc938.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>Where AI Agents Belong in Data Engineering: The Correctness Layer</title>
    <link>https://altimate.ai/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer</link>
    <guid isPermaLink="true">https://altimate.ai/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer</guid>
    <pubDate>Mon, 29 Jun 2026 16:47:17 GMT</pubDate>
    <dc:creator>Simon Späti</dc:creator>
    <category>altimateAI</category>
    <category>harnessengineering</category>
    <category>data-engineering</category>
    <category>AI</category>
    <category>llm</category>
    <description>With ever-changing models, new and better ones coming out every few months, it&apos;s great if we don&apos;t have to rely on them too heavily. The better your tooling, the less dependent you become on any singl</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/2c9f17df-29cf-4ff3-902c-5d6162b044ae.jpg" alt="Where AI Agents Belong in Data Engineering: The Correctness Layer" /></p>
<p>With ever-changing models, new and better ones coming out every few months, it's great if we don't have to rely on them too heavily. The better your tooling, the less dependent you become on any single model. That's also why the deterministic harness matters: a correctness layer that lets you reproduce outputs and trace lineage regardless of which model you're running underneath. This is especially true during maintenance or extending the project, where verification is the real job.</p>
<p>The danger isn't only a crash or an error message, but a wrong number that didn't break. It might be a clean query, but it introduces duplicated rows.</p>
<p>In this article, we go through the three levels of AI agents in data engineering, how to structure projects so the AI delivers its best outcomes, and how dedicated agents with a deterministic core help us build higher-quality pipelines — ones we can actually trust. And we look at a practical example of how it works with a blast radius analysis.</p>
<h2>The Three Levels of AI Agents in Data Engineering</h2>
<p>Why should we use agents for data engineering? And at what levels can agents help us productively? As LLMs will always have some error tolerance, as humans do too, we need a way to be more confident in producing the code.</p>
<h3>Chat-phase, Autonomous and Dedicated Tooling</h3>
<p>There are different levels of confidence and levels on which the agents can help us.</p>
<ol>
<li><p>The initial <strong>chat-phase</strong>: the development where we prompt Claude or ChatGPT. The model tries to understand the context based on what it has access to. It takes a decent amount of tokens, as it needs to scan everything from scratch.</p>
</li>
<li><p>The <strong>autonomous approach</strong>, where Claude Code or Codex also have access to the tools humans have, mostly the CLI on the terminal, making it possible to query Postgres with psql or read from S3 or Parquet with DuckDB to verify queries and data. A much higher quality outcome.</p>
</li>
<li><p><strong>Dedicated agents</strong> for the task at hand. E.g., for data, the tools know dbt or know how to transpile SQL code deterministically, meaning not from training data only, but with an actual tool that does it much faster and more reliably. Built-in checks and features a "general" agent can't provide.</p>
</li>
</ol>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/B1cu2JQzGe.png" alt="svg-ai-agent-levels 1" style="display:block;margin:0 auto" />

<p><em>Showcasing the three levels of AI agents in data engineering</em></p>
<p>Ideally, we'd want to always use the dedicated tools, but there isn't always one.</p>
<h3>Where in the DE Lifecycle Each Level Actually Helps</h3>
<p>BI Dashboards vs. Plumbing the Data Pipelines, or Creating Source Ingestions, or Maintaining? For data engineering, the question is not only if there is dedicated agent tooling, but also on what part of the <a href="https://www.oreilly.com/library/view/fundamentals-of-data/9781098108298/?ref=ssp.sh">data engineering lifecycle</a> AI agents can help data engineers and analysts the most, and potentially even domain experts?</p>
<p>The lifecycle contains the ingestion part, ETL, or understanding the business in great detail, or is it just to visualize the result? Or should it cover maintenance in case of overnight ETL errors, or the full data lifecycle?</p>
<p>In general, before we go into more details later, agents can help us on the full cycle, but it always depends on who you are and what role you play. Building from scratch with <strong>no knowledge</strong> or <strong>seniority</strong> is dangerous. Why? Because they can't verify if the produced code is correct. Okay for a side project or a proof of concept, but not for actual production.</p>
<h3>What's the Engineering Discipline for Working with AI?</h3>
<p>There's also a part that is less technical, a way of guiding the agents in the right direction. Especially if we want to safely use it in large projects or organizations, we can't just let it run without guidance.</p>
<p>For that we need:</p>
<ol>
<li><p>clear <strong>project structure</strong> in which the agents can flourish. The more is given, the fewer tokens are used for this work, and it will be more aligned across the project. (Another reason a deterministic workflow such as <code>uv init</code> is best, because it will always be the same).</p>
</li>
<li><p>build with clear <strong>instructions</strong> (<a href="https://www.altimate.ai/skills">agentic skills</a>, <a href="https://github.com/obra/superpowers">superpowers</a>, etc.) on how the tools are used (basically providing CLIs and API documentation). This is the bulk of the work anyway. That's the data architecture, the brainstorming with fellow humans before you build something, instead of missing a key insight in the beginning and then letting the agent run down the wrong path. Also, be realistic: prompting "be correct" or "use state-of-the-art" won't make it more correct or more state-of-the-art than the model was trained on. So if it's a rather new architecture, it's a must that you provide these links and hints.</p>
</li>
<li><p><strong>set up</strong> the project in a modular fashion, so the agents cannot break the whole project if they make a small change, so you don't end up in a scenario like <a href="https://xkcd.com/2347/">dependency hell</a> with everything dependent on each other.</p>
</li>
<li><p>use a <strong>declarative approach</strong>, with descriptive configuration that says the what and not the how, so that you can <strong>collaborate</strong> on these configs with the agents, version them, and easily revert or change something, as well as decouple the implementation logic from the actual business logic.</p>
</li>
</ol>
<p>With these steps, you can get the best out of the agents of today. I'd say the model matters less, but the structure does, and as Mario says, so does the workflow approach. For example, extensively plan (the process before writing a single line) and correct the model before any implementation that could lead down the wrong path is written.</p>
<p>Also, don't overthink it. But this is only the workflow and learning the <strong>soft skills and discipline of working with agents</strong>. How does that look in a real-world project?</p>
<blockquote>
<p>!Note:</p>
<p>The key is to get use out of AI, not to get more work. E.g., most developers used to think about the problem. Today, most drown in PRs. When the AI tooling gets better, AI can provide more quality code that is correct, that needs less review or fewer iterations, which means fewer PRs and less work for the developers to go through.</p>
</blockquote>
<h2>The Correctness Layer for Data Engineers</h2>
<p>A key insight is that AI agents should support the "human in the loop" for <strong>correctness</strong>, or a <a href="https://blog.altimate.ai/the-correctness-layer-in-ade">correctness layer</a>. And rather than making more work to verify more code, we should be confident in the process and know that the code it produces is verified and ultimately correct.</p>
<p>But how do we get more "correct" work and a layer in which we can verify it? The biggest argument is a deterministic-validation architecture in full. E.g., <a href="https://github.com/AltimateAI/altimate-code">Altimate Code</a> splits the agent into a probabilistic layer on top and a deterministic Rust/TS layer underneath that does the actual SQL ops such as parsing, validating, and equivalence checks, so that the agent itself never has to be trusted on those questions.</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/BklE61QMGl.png" alt="image" style="display:block;margin:0 auto" />

<p><em>An example of how Altimate Code is built with its probabilistic agent, deterministic harness, and deterministic core | Image from the article</em> <a href="https://blog.altimate.ai/the-correctness-layer-in-ade"><em>The Correctness Layer: Why Data Agents Need Determinism</em></a></p>
<p>Altimate Code, for example, is built on a probabilistic agent, deterministic harness, and deterministic core. The <strong>probabilistic agent</strong> with the LLM does the creative work of reading intent, picking a strategy, drafting SQL, summarizing results, and recovering when something goes wrong.</p>
<p>Below the boundary sits the <strong>deterministic harness</strong>, a TypeScript layer that intercepts every tool call: a dispatcher checks <code>hasNativeHandler</code> before the call runs, and routes it either to a native, deterministic handler or back to the model. Those handlers don't reimplement logic themselves, they call into the <strong>deterministic core</strong>, a Rust engine (<code>altimate-core</code>) that exposes SQL operations as pure functions over ASTs and schemas, wired in via napi-rs bindings. Parsing, validating, transpiling, checking query equivalence, diffing schemas, extracting column lineage, diffing rows across warehouses — all of it runs sub-millisecond, and all of it returns the same answer on the same input, every time.</p>
<p>Like a compiler, the agent never <em>decides</em> whether two queries are equivalent or a column exists upstream. Instead, it calls a function that proves it against the parsed AST and the schema, the same way a type-checker proves a program compiles rather than guessing.</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/rkxihk7Mfg.svg" alt="svg-correctness-layer" style="display:block;margin:0 auto" />

<p><em>How the correctness layer adds additional verification</em></p>
<p>That's the distinction that makes the output easier to review, as factual checks have been run and the output is either correct, or there's a bug that it can fix directly. The rest a human can re-verify. On the dilemma of having stopped to hand-write code and approving it faster than humanly possible to check, you can also read more at <a href="https://blog.altimate.ai/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale">You Are the Trust Layer</a>.</p>
<blockquote>
<p>!Note: There's another factor: being wrong</p>
<p>Bare agent use might be cheap, but only until they're wrong, and then the cost is unbounded.</p>
</blockquote>
<h3>Improvements for Better Usage of Tokens</h3>
<p>Altimate, or data engineering agents that have deterministic functions and integrated understanding of how to work, can help you save tokens and be token lean (the opposite of <a href="https://en.wikipedia.org/wiki/Token_maxxing">tokenmaxxing</a>, which is popular on Twitter/X, using as many tokens as possible and having an agent running at all times). Because in large enterprises, token costs are a real budget point.</p>
<p>To slow down the tokens, an easy trick is to instruct the model to use fewer tokens and words itself - <a href="https://github.com/JuliusBrussee/caveman/">caveman</a> is a good example of that, but you can also add a singular prompt to your <code>CLAUDE.md</code>, Codex, or model of choice in combination with Altimate Code.</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/Sk096JmGMx.png" alt="image" style="display:block;margin:0 auto" />

<p><em>An example of Altimate Code showing a trace of data lineage and a web UI for it.</em></p>
<p>There's a second, less obvious cost: the token itself isn't a stable unit. When Anthropic shipped Opus 4.7, the same prompt that cost X tokens on 4.6 <a href="https://blog.altimate.ai/the-great-token-heist-of-26">started costing roughly 1.4X</a> (same input, same answer, more tokens, same price per token).</p>
<p>In <a href="https://blog.altimate.ai/the-great-token-heist-of-26">The Great Token Heist of '26</a> , the Altimate team makes the case that "<em>cost-per-token is the wrong number to optimize</em>", since the meter itself can move with a vendor's next model update, and what we should track instead is <strong>cost-per-task</strong>. I fully agree, and this is where deterministic function calls work around that volatility by not using a model/tokens for every task, making it less expensive.</p>
<h2>Typical Use Cases</h2>
<p>In this chapter we go through typical AI agent use cases for data engineering.</p>
<p>There are many of them. You can use them to educate yourself or your team, build production data pipelines, build data apps, and visualize your data in new innovative ways (usually HTML web pages with React and other JavaScript frameworks). But in general, the use cases fit into these approaches:</p>
<ol>
<li><p><strong>Start a new project from scratch example</strong>: Building a data landscape with more open source.</p>
</li>
<li><p><strong>Extending an existing project or data warehouse</strong>: Adding new data pipelines.</p>
</li>
<li><p><strong>Maintaining current setup</strong>: Update and verify it still works when changes come in.</p>
</li>
<li><p><strong>Migration</strong>: Migrate from one database or tooling to the next.</p>
</li>
<li><p><strong>Finding the Blind Spots</strong>: Two similar-sounding IDs might be wrongly used for a join, or missing data in a column that got missed in a nightly load, or anything in between. If agents can do these checks, that would be super beneficial. With more access to CLI, Model Context Layer, and deterministic tooling, these things are truly possible.</p>
</li>
</ol>
<p>Below we go through extending and changing an existing warehouse with a change of column, and using Altimate Code to give us a Blast-radius assessment.</p>
<h3>Showcases: Blast-Radius Example</h3>
<p>A <a href="https://en.wikipedia.org/wiki/Blast_radius">Blast-radius</a> refers to the <strong>potential extent of damage</strong>. For example, before you knock down a wall in your house, you want to know if there's plumbing behind it, electrical wiring within it, or if it's holding up the floor above.</p>
<p>The same is true for a data warehouse or a data project with lots of ETL. For example, if a data engineer cleans up the table <code>fct_orders</code> by joining <code>orders</code> to <code>order_items</code> and summing <code>order_total</code>. It compiles, the dbt tests pass, nothing errors. But the join changes the grain, so any order with several line items now gets counted once per item, and revenue quietly inflates.</p>
<p>It's best to know, before you <strong>rename a column</strong> or add a new join, the downstream (data that comes after the current task) dependencies to the dashboard — that's what the blast-radius report does.</p>
<p>With Altimate Code we can achieve this. Before any change goes through, it maps out the full impact automatically and produces a detailed blast-radius report with what will break, what's safe, what needs someone to sign off, and also performs the changes. Here is what this looks like:</p>
<h4>Rename and Change Columns and Logic</h4>
<p>As an example, in this prepared <a href="https://github.com/sspaeti/ecommerce_demos">ecommerce repo</a> with different DWH layers such as <code>staging -&gt; intermediate -&gt; marts</code>, I prompted this request to change unit from cent to dollars:</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/Bk_d41sfzx.png" alt="image" style="display:block;margin:0 auto" />

<p>It recognized the dbt name and invoked <code>dbt-analyze</code> automatically:</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/HyJcVyjMMg.png" alt="image" style="display:block;margin:0 auto" />

<p>It gave me a full Blast-radius report and the impact my changes would have on the project:</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/r1gsN1jMfg.png" alt="image" style="display:block;margin:0 auto" />

<p>Including semantics only, to point out what's safe and what's not:</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/S1xNhVyozfx.png" alt="image" style="display:block;margin:0 auto" />

<p>With a fixed order to address breaking changes, semantics and docs, and intentionally untouched:</p>
<img src="/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/SJLaE1iMfg.png" alt="image" style="display:block;margin:0 auto" />

<p>Notice, I hadn't said anything about blast analysis or using dbt-analyze. It did it on its own, ran dbt, and analyzed it deterministically.</p>
<p>This shows how <strong>Altimate Code looks behind the walls of data engineering</strong>, just like blast radius analysis.</p>
<p>If you want to see another example and a full blog post on Blast Radius, check out <a href="https://www.altimate.ai/blog/blast-radius-analysis-using-altimate-code">Blast Radius Analysis Using Altimate Code</a>, and what Altimate Code did as in the <a href="https://www.youtube.com/watch?v=Npf7fHK43-k">video</a>. Or Altimate provides many more examples and <a href="https://docs.altimate.sh/examples/">Showcase</a> on their website such as <a href="https://www.youtube.com/watch?v=7MtD0NJjZS4">Migrate SQL Server to Snowflake with dbt</a> or showing how to resolve <a href="https://docs.altimate.sh/examples/#an-upstream-schema-changed-what-just-broke">An Upstream Schema Changed</a>.</p>
<blockquote>
<p>!Note: Connect a model to Altimate</p>
<p>Make sure to connect to a model with <code>/connect</code> and choose an existing subscription with API credits, or any other subscription. I used <a href="https://opencode.ai/zen">opencode zen</a> for my example, which includes e.g. Opus 4.8.</p>
</blockquote>
<h2>Correctness Over Confidence</h2>
<p>I hope you got a better understanding of why AI agents can be genuinely useful, especially when provided with the right tools and applied with the right discipline.</p>
<p>You've also seen how deterministic tooling, purpose-built for data engineering and analytics problems, gets you both better correctness and better token economics than general-purpose agents alone.</p>
<p>Coming back to where we started: not every task needs a level-three agent. A quick chat-phase agent is fine for exploring a dataset or drafting a query you'll review yourself. But the moment that output touches production or serious work, a dashboard, a nightly job, a number someone makes a decision on, you want the deterministic core underneath it, not just a model that sounds confident.</p>
<p>That's the gap <a href="https://github.com/AltimateAI/altimate-code">Altimate Code</a> is built to close. It runs on deterministic functions purpose-built for DE workloads, it's open-source via the OpenCode TUI, and for teams wanting more, there's Altimate Studio — a paid, multi-agent platform with extras like warehouse cost optimization, dbt development acceleration, and migration tooling.</p>
<hr />
<p>Check out <a href="https://github.com/AltimateAI/altimate-code">Altimate Code</a>, it's free and open-source. Give them a star if you like them, and find more information on their <a href="https://help.altimate.ai/">docs</a> and new <a href="https://www.altimate.ai/">website</a>.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/where-ai-agents-belong-in-data-engineering-the-correctness-layer/2c9f17df-29cf-4ff3-902c-5d6162b044ae.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>You Are the Trust Layer</title>
    <link>https://altimate.ai/blog/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale</link>
    <guid isPermaLink="true">https://altimate.ai/blog/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale</guid>
    <pubDate>Mon, 15 Jun 2026 19:38:45 GMT</pubDate>
    <dc:creator>Anand Gupta</dc:creator>
    <category>AI</category>
    <category>Software Engineering</category>
    <category>ai agents</category>
    <category>developer productivity</category>
    <category>llm</category>
    <description>Sometime this year your job changed, and nobody sent the memo. You used to write code. Now you mostly approve it: you read a summary, it looks right, you hit accept, and you&apos;ve moved on before you cou</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale/0762d2d6-5dab-447e-ace9-fd0a35f099a8.jpg" alt="You Are the Trust Layer" /></p>
<p>Sometime this year your job changed, and nobody sent the memo. You used to write code. Now you mostly approve it: you read a summary, it looks right, you hit accept, and you've moved on before you could have checked it even if you wanted to. The machine produces faster than any person can verify, and the distance between what it ships and what you actually confirmed grows every week.</p>
<p>So what does that make you? Not a tool's user. You are managing a labor force whose work you never read, and you are the only check between its confident output and what reaches production. You are the trust layer.</p>
<blockquote>
<p>The defining problem of this era isn't that AI can't do the work. It's that it does the work far faster than anyone can check it.</p>
</blockquote>
<p>I know because I measured it. I wrote a small proxy, pointed it at my own machine, and logged every request that crossed the wire for forty-eight hours. One developer, two days: <strong>11,302 requests across 109 concurrent sessions and sub-agents</strong>. The last change one of those agents handed me had taken it six minutes and something close to an afternoon of human work. <strong>I looked at it for eleven seconds, then hit accept.</strong> I read what surfaced and trusted the rest. So do you.</p>
<p>The first problem with a trust layer made of one person is that it's uneven. How much gets caught depends entirely on who is holding the line. A senior catches a surprising amount by reflex: the function that's subtly wrong, the assumption that doesn't hold. A junior catches less, because spotting the bad answer is the same skill as writing the good one, and that skill is the thing they're still building. And the ten sub-agents your agent spawned that nobody opened? Those are checked by no one at all. Across a real team, the work is thin on checking, and thinnest exactly where no one is looking.</p>
<p>The second problem is worse, because it doesn't care how good you are. Generation is parallel and nearly free: one prompt fans out into ten agents. Your attention is serial and fixed: you read one thing at a time, and there are only so many hours. So as the volume climbs, the fraction any human can actually check falls, and not gently. It heads for zero. The senior's reflexes don't beat this. They just start from a higher number on the way down.</p>
<p>You might assume the part you don't check is mostly harmless, or you'd have noticed by now. I assumed that too, until I scored it. Almost everything the agents produced looked like a correct answer: clear, confident, well-formed. Barely a third of it actually was one, once I checked it against the code and the task in front of it. Looking right and being right turn out to be very different numbers, and the gap between them is exactly the part a quick skim waves through.</p>
<img src="/blog/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale/a3a21996-9f63-456d-8ae2-3419691cef5a.png" alt="" style="display:block;margin:0 auto" />

<p>And the work you don't check doesn't disappear. It ships, things get built on top of it, and (this is what turns a backlog into debt) the next agent reads it as context and repeats it as fact. A wrong assumption from Tuesday is settled truth by Friday, cited in code none of you wrote by hand. You took the debt on to move fast. It accrues interest quietly, and it comes due later: the incident, the rollback, the week spent tracing where the data went wrong.</p>
<blockquote>
<p>The person clicking accept is almost never the person who pays.</p>
</blockquote>
<p>That's why you, personally, feel fine. The cost is displaced. It lands in time, weeks after the commit that caused it, and it lands on other people: the junior who trusts the senior's pace without the senior's reflexes, the teammate who inherits the module, next quarter's version of you. It's also why the best engineer on the team is the most sure there's no problem. He's right about his own desk. He just isn't the one holding the bag.</p>
<p>One developer can absorb this by hand for a while, which is the whole reason it stays invisible. An organization can't. Multiply it across everyone shipping this way and there is no trust layer left, only thousands of accepts a day, a rising balance of unverified work, and no single place that can tell you which of it was real.</p>
<p>Today the trust layer is you: by reflex, in the seconds between accepting one diff and starting the next. That was never going to hold. The only open question left is whether you replace it on purpose, with verification that runs as fast as the work is produced, or keep paying the debt until it picks the moment to collect.</p>
<hr />
<p><em>Numbers from a local proxy run against one machine over a 48-hour window: 11,302 requests, 109 concurrent sessions and sub-agents, and a 47-trace correctness sample in which 96.9% of output looked right and 37.5% was actually right. Measured, not modeled.</em></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale/0762d2d6-5dab-447e-ace9-fd0a35f099a8.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>DeepSeek Cost 62% Less Than Claude. The Surprising Part Wasn&apos;t the Savings…</title>
    <link>https://altimate.ai/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark</link>
    <guid isPermaLink="true">https://altimate.ai/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark</guid>
    <pubDate>Wed, 10 Jun 2026 14:33:11 GMT</pubDate>
    <dc:creator>Syed Haider</dc:creator>
    <dc:creator>Surya Iyer</dc:creator>
    <category>AI</category>
    <category>llm</category>
    <category>Deepseek</category>
    <category>data-engineering</category>
    <category>ai agents</category>
    <description>If you&apos;re running an AI agent on data (pipeline diagnostics, schema exploration, ad-hoc SQL, lineage queries), you&apos;ve looked at the model bill and asked the same question we did:

&quot;The cheaper model o</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/03ea3e21-350a-45e9-87d7-7581b8d9aa92.jpg" alt="DeepSeek Cost 62% Less Than Claude. The Surprising Part Wasn&apos;t the Savings…" /></p>
<p>If you're running an AI agent on data (pipeline diagnostics, schema exploration, ad-hoc SQL, lineage queries), you've looked at the model bill and asked the same question we did:</p>
<blockquote>
<p><em>"The cheaper model on the leaderboard is only a few points behind the one I'm using. The endpoints are drop-in compatible. The agent code doesn't care which backbone is wired in. Why shouldn't I switch?"</em></p>
</blockquote>
<p>That's a defensible question. It's also a question with a more interesting answer than the leaderboard suggests.</p>
<p>We're going to walk through what we found when we ran the swap: Claude Sonnet 4.6 to DeepSeek v4 pro inside the same data agent, run across the same benchmark, with the same workspace, prompts, and tools. The accuracy difference is small and roughly what the leaderboard predicts. The behavioral difference is not. By the end of this post we'll have a concrete framework for thinking about LLM selection in an agent context that's a lot more useful than "<em>which model is on top of which leaderboard this week.</em>"</p>
<p>Throughout, the only thing we change is the backbone model.</p>
<p>*<strong>Note:</strong> We did not compare against Claude Opus series since Opus would intensify the cost gap (roughly 5× Sonnet's per-trial cost) without changing the model family. We plan more inter- and intra-model family comparisons soon.</p>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/61cbe1a4-8674-4c1b-bdc1-a51de5e41b90.svg" alt="" style="display:block;margin:0 auto" />

<p><em>Same task — Beyoncé's "Get Me Bodied" on DAB’s music_brainz dataset. The dots are tool calls. The gray bars are narration chunks. You can tell the models apart without looking at the model field.</em></p>
<h2><strong>The setup, in two paragraphs</strong></h2>
<p>We use <a href="https://github.com/altimateai/altimate-code">altimate-code</a>, the open-source agent runtime behind our data engineering platform. It's the harness currently sitting at #1 on the <a href="https://ucbepic.github.io/DataAgentBench/">DataAgentBench (DAB)</a> leaderboard for Pass@1 stratified accuracy, scored at 0.6320 with GPT 5.5 and Claude Sonnet 4.6. DAB is UC Berkeley's data-agent benchmark: 54 queries across 12 real-world datasets (Postgres + MongoDB + SQLite + DuckDB), 5 trials per query, 270 trial runs per submission. Real schemas, real ambiguity, validators that check the exact shape of the answer.</p>
<p>For this post we ran two complete Pass@5 passes through altimate-code: one with Claude Sonnet 4.6, one with DeepSeek v4 pro. 270 trials each. 540 trials total. Everything else (agent code, prompts, tools, validators, dataset hints, workspace setup) stayed identical. The result is a clean A/B with a single variable. That's what makes the contrast interesting.</p>
<h2><strong>The numbers that the leaderboard would show you</strong></h2>
<p>Here's how the two runs compare on the dimensions a leaderboard would surface:</p>
<pre><code class="language-plaintext">                          Sonnet 4.6      DeepSeek v4 proᵃ
Stratified Pass@1            60.4%             56.9%
Raw Pass@1                   63.0%             60.0%
Cost per trial               $0.76             $0.29
Median duration / trial      4 min             9 minᵇ

ᵃThis run has not been sumbitted to DAB, we're working on an improved approach.
ᵇDeepSeek latency measured via OpenRouter without upstream-provider pinning; 
OpenRouter's routing across DeepSeek's underlying providers contributes to wall-clock variance.
</code></pre>
<ul>
<li><p>Accuracy gap: 3.5 stratified points (the benchmark metric).</p>
</li>
<li><p>Cost gap: 2.7× cheaper for DeepSeek.</p>
</li>
<li><p>Latency gap: 2.2× faster per trial for Sonnet.</p>
</li>
</ul>
<p>If you're running an overnight batch workload where wall-clock doesn't matter, those numbers point at DeepSeek. If you're running an interactive agent where users are waiting, they point at Sonnet. That's the surface-level read, and it's not wrong.</p>
<p>It's also incomplete in ways that turn out to matter.</p>
<h2><strong>The trace tells a different story</strong></h2>
<p>We picked the model swap as the only variable so we could look at everything else.</p>
<p>Inside an agent run, the score is one bit of information: the final ANSWER, did it pass or fail. The trace (every tool call, every text emission, every step boundary, with timestamps) is thousands of bits. The agent loop produces a <code>events.jsonl</code> file per trial, and once you start reading them side-by-side, the score gap stops being the interesting number.</p>
<p>Here’s a snippet:</p>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/28ab6597-0184-4c7d-b107-128127bd4712.svg" alt="" style="display:block;margin:0 auto" />

<p>The trace signature is what an operator stares at when something goes wrong in production at 3 AM. It's what you log, what you alert on, what you debug from. We found that the signature changes more when you swap the model than the accuracy does. By a lot.</p>
<p>Here's what that looks like, concretely.</p>
<h2><strong>Finding 1: One model talks. The other doesn't.</strong></h2>
<p>Per trial:</p>
<pre><code class="language-plaintext">                              Sonnet 4.6                DeepSeek v4 pro
Chat-text events (mean)             13                       10
Characters of narration (mean)      5.7 k                    1.7 k
Tools called — mean                 36                       36
Tool calls — median                 32                       36
Tool calls — min                    0                        0
Tool calls — max                    82                       75
</code></pre>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/7a761e9c-d563-4f47-9042-0a72cc81664f.svg" alt="" style="display:block;margin:0 auto" />

<p>Both models handled the same workload with the same tool volume. Sonnet writes about 3× more chat text along the way. It narrates as it works ("Let me check the schema for the orders table" / "I'll filter for active customers first" / "Trying a different join condition"). DeepSeek does its planning silently and only surfaces what it has to.</p>
<p>This shows up in the cost structure too. Sonnet writes 49 k tokens into Anthropic's prompt cache per trial and reads 1.22 M back from it; reasoning tokens are zero. DeepSeek writes nothing to a prompt cache, but burns 8 k reasoning tokens per trial doing chain-of-thought inline.</p>
<p>The downstream consequences are concrete:</p>
<ul>
<li><p>If you're tailing logs from an agent in production, Sonnet sounds like a thinking colleague. DeepSeek sounds like a quiet one.</p>
</li>
<li><p>If you're building token-cost alerts, they'll be calibrated for one and miss the other. Sonnet's bill is input tokens + prompt cache. DeepSeek's is reasoning tokens, with no cache line at all. So a Sonnet-tuned alert ("input spend spike", "cache hit-rate drop") sits silent on DeepSeek while reasoning-token cost you're not watching adds up.</p>
</li>
<li><p>If your platform's observability is built on chat-text logging, swapping to DeepSeek will quietly cut your visibility by two-thirds.</p>
</li>
</ul>
<p>None of this affects the accuracy column on the leaderboard. All of it affects your team building on top of these models.</p>
<h2><strong>Finding 2: One model commits early. The other doesn't always commit.</strong></h2>
<p>altimate-code reads the agent's final answer from a file called ANSWER. Every <code>write</code> tool call against that file is a timestamped event. We plotted the first ANSWER write per trial as a fraction of trial elapsed:</p>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/208bd216-76ea-4aa7-a7ed-c58d4ed2adb1.svg" alt="" style="display:block;margin:0 auto" />

<p>Sonnet's median first commit lands around 70% of the way through a trial. DeepSeek's lands around 90%. And the "never" row is the operationally important one: <strong>79 of 270 DeepSeek trials never wrote anything to ANSWER at all.</strong> For Sonnet, that number is 32.</p>
<p>These are two strategies, both legitimate. Sonnet commits early and refines: writes a first draft mid-trial, then rewrites it as confidence grows (mean: 1.47 ANSWER writes per trial). DeepSeek explores until forced to commit, then commits once (mean: 0.88 writes per trial).</p>
<p>Why DeepSeek explores-then-commits is partly architectural. Its reasoning models emit reasoning_content and content on two parallel channels (<a href="https://api-docs.deepseek.com/guides/reasoning_model">DeepSeek API docs</a>). The agent loop consumes content; reasoning_content is inspection-only and must be stripped before resubmission (the API 400s otherwise). DeepSeek plans privately in the reasoning channel and bursts the plan into content as tool calls + ANSWER in one transition. Sonnet has no such split: its chain-of-thought shares the channel the loop consumes, so drafts and retractions stream out as visible turns.</p>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/9f80f9da-c343-441e-9fd4-32870e03164e.svg" alt="" style="display:block;margin:0 auto" />

<p>If you're building anything where users see partial progress (a dashboard, a streaming UI, an agent that hands off intermediate results), Sonnet gives you a draft to show by minute two. DeepSeek leaves you with an empty file for eight minutes, and almost a third of the time, leaves it empty forever.</p>
<h2><strong>Finding 3: One model asks the database questions. The other writes scripts.</strong></h2>
<p>Look at the tool-call distribution across all 270 trials per model:</p>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/8dd290f6-13f1-40a0-b679-10fe639fe044.svg" alt="" style="display:block;margin:0 auto" />

<p>The agent and tool surface were identical; the tool preferences were not.</p>
<p>Sonnet falls back to bash 45% more often than DeepSeek. It runs Python scripts for filtering, aggregating, formatting. When in doubt, it writes code.</p>
<p>DeepSeek prefers the native data tools the harness exposes. It inspects schemas 2.7× more often. It runs SQL through <code>sql_execute</code> 64% more often. When in doubt, it asks the database.</p>
<p>The discovery cadence diverges before the first SQL even runs. Mean schema-related calls before the first SQL execution: 2.8 for Sonnet, 4.9 for DeepSeek. DeepSeek does a column-by-column tour before writing any SQL. Sonnet reads the prompt, takes one schema snapshot, and gets to work.</p>
<p>Both rhythms produce correct answers on plenty of queries. They get there with different tool budgets and different turn structures.</p>
<blockquote>
<p>If your platform logs the shape of tool calls in production, you can identify which backbone is running without looking at the model field.</p>
</blockquote>
<h2><strong>Finding 4: When they fail, they fail differently</strong></h2>
<p>This is the finding we found most operationally consequential.</p>
<p>Every failed trial fits one of four shapes:</p>
<pre><code class="language-plaintext">                            Sonnet 4.6      DeepSeek v4 pro
Empty (nothing written)        7 (3%)         27 (10%)
Short wrong (single value)    43 (16%)        26 (10%)
Medium wrong (small table)    30 (11%)        33 (12%)
Long wrong (multi-row)        20 (7%)         22 (8%)
Total failures               100             108
</code></pre>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/4955d3db-74e0-4108-aa0d-ca0023a8b439.svg" alt="" style="display:block;margin:0 auto" />

<p>Sonnet's failures cluster on <em>short wrong</em>: confident commits to a wrong value. DeepSeek's cluster on <em>empty</em>: the agent worked, explored, iterated, and never wrote anything.</p>
<p>The total failure count is the same; the shapes are opposite. Both shapes have architectural roots.</p>
<p>DeepSeek's reasoning API can return HTTP 200 with <code>reasoning_content</code> populated but <code>content</code> empty, meaning the model reasons through to a conclusion without ever generating output text. The failure mode is tracked in <a href="https://github.com/deepseek-ai/DeepSeek-R1/issues/314">DeepSeek-R1 issue #314</a>: "the status code returned is 200 (indicating a successful request in the HTTP protocol sense), the actual content of the response is empty." The issue was closed stale without a fix. Sonnet has the opposite problem for the opposite reason: with no separate reasoning channel, its planning happens in the same <code>content</code> stream the loop consumes. Drafts surface as soon as the model has a candidate, and once a candidate is in ANSWER there's no separate "verify-before-commit" gate to slow it down. The model <em>satisfices</em>: it picks the first plausible answer, polishes the prose around it, and moves on. That's how “short wrong” gets produced: a confident commit on partial evidence, with the verification step folded into the same channel that wrote the answer in the first place.</p>
<p>Here's a concrete example. DAB’s “GitHub Repos” query 3 asks for the count of Shell-language commits in Apache-2.0 repos under a length filter. The ground truth is <code>1077</code>.</p>
<pre><code class="language-plaintext">Sonnet:   "963
114"   ← committed close-but-wrong on turn 8
DeepSeek: "1077"       ← landed correctly after exhaustive schema inspection
</code></pre>
<img src="/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/e648890e-6ef2-4a67-bf91-6c7a73ae5a8f.svg" alt="" style="display:block;margin:0 auto" />

<p>DeepSeek did 40 tool calls, including 4 <code>schema_inspect</code> calls and 12 <code>sql_execute</code> iterations. It got there because it kept asking. Sonnet did 21 tools, jumped to bash at turn 8 with a count that was nearly right, and never noticed it was wrong. DeepSeek won this query 4 out of 5 trials. Sonnet won 0.</p>
<p>For an operator, the two failure modes have different downstream costs:</p>
<ul>
<li><p><strong>Vocal-wrong</strong> (Sonnet's signature) gives you a bad answer that may pass type checks and propagate to consumers. The downstream system sees a number and assumes it's right.</p>
</li>
<li><p><strong>Silent-stuck</strong> (DeepSeek's signature) gives you nothing: a missing row that is easy to detect with a presence check but hard to debug without the trace.</p>
</li>
</ul>
<p>Which is worse depends on what your downstream consumers do. If you have validators downstream that can re-check correctness, silent-stuck is more recoverable. If you don't, vocal-wrong is the silent killer.</p>
<h2><strong>When the signature disappears</strong></h2>
<p>There are times, however, when models do <em>not</em> fail differently.</p>
<p>When a question is clean (the schema is obvious, the format is pinned down, the dataset hint spells out the join recipe), Sonnet and DeepSeek behave almost identically. We watched this on a question from DAB's <code>bookreview</code> corpus (query 3) that asks for a multi-row table from columns that store Python-dict syntax as text. Both models passed it. Both took exactly 27 tool calls. The first eight tools in each trace were nearly identical: read question, read format_hint, list warehouses, index schema, inspect a table, write the SQL.</p>
<p>The same effect shows up when the agent has good orientation upstream of the main loop. We run a pre-orientation pass where a lighter model walks the schema, samples rows, identifies non-obvious column formats, and proves out join candidates with mechanical probes. The output gets dropped into the agent's workspace as a single markdown file. When that file is well-formed, you can't tell the models apart from the trace.</p>
<p>The trace signature shows up at the <em>edges</em> of the agent's capability, where it has to decide for itself when to commit, how aggressively to explore, what to do when stuck.</p>
<p>So before you assume model selection matters for your workload, look at your queries. If most of them are clean (well-documented schemas, unambiguous prompts, validators that accept reasonable variants), the model choice may genuinely not move your needle. Pick on cost. If your real queries push the agent into open-ended decisions (which is what most production data-engineering work actually does), the trace signature is what you should be evaluating.</p>
<h2><strong>How we choose now</strong></h2>
<p>A short field guide, based on what we measured:</p>
<p><strong>Pick Sonnet 4.6 when:</strong></p>
<ul>
<li><p>You need progress visibility mid-run. For dashboards, streaming UIs, and partial-trace debugging, you need incremental output. Sonnet writes a draft answer at the 70% mark and improves it. DeepSeek doesn't write anything for 90% of the trial, and a third of the time, never writes anything.</p>
</li>
<li><p>Latency matters per trial. Sonnet finishes in ~4 minutes median; DeepSeek in ~9. For interactive use, the gap is felt.</p>
</li>
<li><p>Silent failures are expensive downstream. Vocal-wrong is easier to detect than silent-stuck. If your pipelines don't double-check the agent's output, you want it to commit (so you can catch wrong answers) rather than disappear (so you don't even know it failed).</p>
</li>
</ul>
<p><strong>Pick DeepSeek v4 pro when:</strong></p>
<ul>
<li><p>Cost matters more than wall-clock. DeepSeek runs at 38% of Sonnet's per-trial cost for similar accuracy on this benchmark, making the math straightforward for overnight batch, retroactive backfills, and async report generation.</p>
</li>
<li><p>The agent needs to explore. DeepSeek's tendency to inspect the schema thoroughly before writing SQL is the right behavior when the schema is unfamiliar and the question demands precision.</p>
</li>
<li><p>You have downstream validators that catch silent-stuck. If your platform notices missing outputs and can retry, DeepSeek's caution costs you less than Sonnet's overconfidence might.</p>
</li>
</ul>
<p><strong>Run both when:</strong></p>
<ul>
<li>You're doing consensus or majority voting. The two backbones disagree on 19% of trials in our run. That's a real ensemble margin, not noise. A judge model can pick the right answer often enough to lift the combined score above either alone.</li>
</ul>
<p><em><strong>Case in point:</strong></em> <em>In this comparison, Sonnet and DeepSeek disagreed on 51 trials. A perfect oracle judge over those would lift ensemble Pass@1 by ~9-10pp; a realistic LLM judge by ~3-5pp. Full consensus math and a real judge run is a follow-up.</em></p>
<p>We use all of the above in production. <a href="https://altimate.sh">altimate-code</a> is built to make this choice cheap: any backbone, swappable per workload, same trace format regardless. The selection logic is yours. The decision is yours.</p>
<h2><strong>A footnote on substrates</strong></h2>
<p>This post is the operational complement to an argument we made earlier in <a href="https://blog.altimate.ai/the-correctness-layer-in-ade"><em>The Correctness Layer in ADE</em></a>. That one argues that for the parts of data engineering that have deterministic ground truth (two queries are equivalent, a lineage edge exists, a row-level diff is correct), the LLM is the wrong substrate. The substrate should be deterministic code.</p>
<p>The argument here is the complement: even when you do leave a task to the LLM, <em>which</em> LLM you pick changes the operator experience. The substrate is still the story. The LLM is just the part of the substrate that varies the most when you swap providers.</p>
<h2><strong>If you want to look yourself</strong></h2>
<p>Everything in this post is reproducible. <a href="https://altimate.sh">altimate-code</a> is <a href="https://github.com/AltimateAI/altimate-code">open source</a>. DataAgentBench is open. You can obtain the per-trial <code>events.jsonl</code> files which preserve every tool call, every step boundary, every token count, every chat emission. The two runs we compared above are from our own <code>benchmark_runs</code> collection; the analysis script that produced the numbers is in the repo. If your team is making a similar swap, the same kind of diff is one fork and a few hours of compute away.</p>
<h2>Conclusion</h2>
<p>The leaderboard tells you what a model can do on a benchmark. The trace tells you what your agent will look like in production. We built <a href="https://altimate.sh">altimate-code</a> to win on both.</p>
<p>That's why we sit at <a href="https://web.archive.org/web/20260608100121/https://ucbepic.github.io/DataAgentBench/">#1 on DataAgentBench</a> with Sonnet, and why the same runtime runs DeepSeek at 38% of the cost just as cleanly. The tools, prompts, and trace format are identical across both. The model becomes a variable per workload, not a quarterly commitment.</p>
<p>The runtime carries its share too. Tools emit a compact, structured payload to the model and a richer, human-readable one to the UI, so the agent's context window isn't burned on formatting it'll never read. Long sessions get compacted instead of truncated. Token budgets stretch further on every backbone you point at it.</p>
<p>Pick the model that fits the workload. Pick the runtime that doesn't lock you to one.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/deepseek-vs-claude-sonnet-ai-agent-benchmark/03ea3e21-350a-45e9-87d7-7581b8d9aa92.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>The Great Token Heist of ‘26</title>
    <link>https://altimate.ai/blog/the-great-token-heist-of-26</link>
    <guid isPermaLink="true">https://altimate.ai/blog/the-great-token-heist-of-26</guid>
    <pubDate>Mon, 01 Jun 2026 20:15:13 GMT</pubDate>
    <dc:creator>Surya Iyer</dc:creator>
    <dc:creator>Syed Haider</dc:creator>
    <category>altimateAI</category>
    <category>agentic AI</category>
    <category>Tokenomics</category>
    <category>openai</category>
    <category>claude-code</category>
    <description>Your LLM provider charges by the token, but a token is not a portable unit of work, a unit of meaning, or any unit you can compare across vendors. It only has meaning inside one vendor&apos;s system and lo</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/the-great-token-heist-of-26/a164d003-f725-473b-a6e6-a026ab05d821.jpg" alt="The Great Token Heist of ‘26" /></p>
<p>Your LLM provider charges by the token, but a token is not a portable unit of work, a unit of meaning, or any unit you can compare across vendors. It only has meaning inside one vendor's system and loses it the moment you step outside. The token is a currency: vendors mint it, vendors re-denominate it, and the exchange rate with English (meaning how many tokens it takes to express the same sentence) is theirs to set. So when two vendors quote the same dollars-per-token, they are still quoting in different currencies.</p>
<p>On April 17, 2026, the day after Anthropic shipped Claude Opus 4.7, a Hacker News user named <em>anabranch</em> posted a public leaderboard they had built at <a href="http://tokens.billchambers.me">tokens.billchambers.me</a> with crowdsourced before-and-after token counts on the same prompts run through Opus 4.6 and Opus 4.7. The thread title, <a href="https://news.ycombinator.com/item?id=47816960">"Opus 4.7 to 4.6 Inflation is ~45%"</a>, climbed to 117 points before lunch. anabranch's summary: <em>"It can be more than 2x for small prompts."</em></p>
<p>The comments filled with developers reporting specific impacts on their bills. <em>hgoel</em>, on the Claude Max 5x plan, <a href="https://news.ycombinator.com/item?id=47817737">hit their five-hour usage limit in under two</a>. <em>tiffanyh</em> <a href="https://news.ycombinator.com/item?id=47817627">exceeded the weekly limit after seven prompts on a single-file HTML/CSS/JS project under 300 lines</a>. <em>KellyCriterion</em>: <a href="https://news.ycombinator.com/item?id=47817801">"killed my weekly limit with just three prompts."</a> <em>manmal</em> put the number on it: <a href="https://news.ycombinator.com/item?id=47817534">"The same prompt costs roughly 30% more now, for input."</a></p>
<p>None of this was a price change. <a href="https://www.anthropic.com/news/claude-opus-4-7">Opus 4.7 launched at the same $5 per million input tokens and $25 per million output as 4.6.</a></p>
<p>Independent measurements followed within days. Simon Willison upgraded his Claude Token Counter to compare the two models on the same input and <a href="https://simonwillison.net/2026/apr/20/claude-token-counts/">posted</a>: <em>"Opus 4.7 does appear to use 1.46x times the tokens for text"</em>, with up to 3× for images, priced the same as Opus 4.6 on a per-token basis. <a href="https://openrouter.ai/announcements/opus-47-tokenizer-analysis">OpenRouter ran the numbers across more than a million real customer requests</a> and published a bucketed breakdown: 32–45% more native tokens for equivalent text (highest on prompts under 2,000 tokens), with a 12–27% increase in net cost after prompt caching absorbed some of the inflation.</p>
<p>What changed was not the price per token. It was the token itself. The same prompt that cost you X tokens on 4.6 now costs roughly 1.4X on 4.7: same input, same answer, same work. The vendor changed the resolution. If that sounds like a camera going from 12 to 18 megapixels, Anthropic would accept that comparison: more resolution, better model, same price per unit. But a megapixel upgrade is a one-time capability you choose. This tokenizer change bills you per pixel on every shot, cannot be switched off, and shipped with no announcement. And more megapixels never guaranteed a better photo, only a bigger file. More tokens do not guarantee a better answer. They guarantee a bigger bill.</p>
<h1>The currency got re-denominated</h1>
<p>Buried in Anthropic's <a href="https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-7">migration guide</a> is one easy-to-miss sentence: Opus 4.7 uses a new tokenizer that <em>"may use roughly 1x to 1.35x as many tokens"</em> as previous models, varying by content. The price per token did not move; the number of tokens required to express the same English sentence did.</p>
<p>The honest defense is that this is an upgrade: a finer tokenizer can mean better resolution and better answers, and you simply pay in more tokens for them. But "better answers" is a measurable claim. If the quality is real, it shows up as a higher success rate and the cost per finished task still holds. If it does not, you are paying more tokens for the same result. The catch is that they shipped the cost with no announcement and no opt-out, while leaving the "better outcomes" half for you to verify on your own bill.</p>
<p>If this happened in a fiat currency, we would call it a redenomination: the kind of operation central banks use when they need to recalibrate without admitting they are recalibrating. Your salary stays "the same" in the new currency, but the new currency buys 30% less coffee. Anthropic, of course, does not have the obligations of a central bank, so there is no announcement, no press conference, and no notice period. The tokenizer is part of the model. It changes when the model changes.</p>
<p>The Hacker News reactions were not just complaints about bills. They were the predictable response to opacity. <em>Shailendra_S</em>, a bootstrapped founder, <a href="https://news.ycombinator.com/item?id=47817588">argued that 45% inflation breaks the unit economics for most indie products</a> and pushes builders toward open models, or back to the more token-efficient Opus 4.5. <em>dakiol</em> <a href="https://news.ycombinator.com/item?id=47817610">announced his team had dropped Claude entirely</a>. <em>Boris Cherny from the Claude Code team</em> <a href="https://news.ycombinator.com/item?id=47817526">showed up in the thread</a>, but to address a separate complaint about over-fixated safety warnings, not the cost question. The cost question is hard to address. The currency really did get smaller, and the vendor can keep calling it "the same price."</p>
<p><em>"Nobody raised prices. The currency got smaller."</em></p>
<h1>There is no standard token</h1>
<p>Anthropic's redenomination is not unusual. It is the rule, dressed up as an exception.</p>
<p>Tokens are made by tokenizers, which are deterministic functions that split text into integer IDs. Each vendor trains its own. OpenAI's <a href="https://github.com/openai/tiktoken">tiktoken</a> is open-source: you can download the vocabulary files and count locally before you pay. GPT-3.5 and GPT-4 use <a href="https://github.com/openai/tiktoken"><code>cl100k_base</code></a>, with 100,256 entries. GPT-4o, GPT-5, and the o-series use <code>o200k_base</code>, with 200,019. The transition from one to the other in 2024 was not priced as a change. It was, of course, a change.</p>
<p>The pattern repeats across vendors. <a href="https://huggingface.co/blog/llama3">Llama 2 to Llama 3 jumped from a 32K to a 128K vocabulary</a>, and Meta says that buys up to 15% fewer tokens for the same text. <a href="https://mistral.ai/news/mistral-nemo">Mistral's Tekken tokenizer</a>, introduced for NeMo and Pixtral, compresses code about 30% more efficiently than its SentencePiece predecessor, and Korean and Arabic by 2–3×. <a href="https://docs.rs/gemini-tokenizer">Gemini's tokenizer</a>, currently a 262,144-token SentencePiece model shared with Gemma 3, has rotated through versions across Gemini 1.5, 2.x, and 3.x. DeepSeek's <a href="https://arxiv.org/abs/2412.19437">V3 paper</a> documents a 100K → 128K vocabulary expansion from V2.</p>
<p>The vendor with the most aggressive policy of opacity is Anthropic. The legacy <code>claude-v1-tokenization.json</code> was published for Claude 1 and never again. For Claude 3, 3.5, 4, and 4.7, the only authoritative way to count tokens is to call Anthropic's <a href="https://platform.claude.com/docs/en/build-with-claude/token-counting"><code>count_tokens</code> endpoint</a>. The repository <code>javirandor/anthropic-tokenizer</code> is the community workaround, reverse-engineered by asking Claude to repeat text and observing what comes back. It is approximate, and for many teams it is also the only way to estimate Claude cost without a round-trip to Anthropic's servers.</p>
<p>You can quote two vendors at the same dollar-per-million-token. You cannot quote them in the same units.</p>
<h1>The AI exchange rate is not the same for everyone</h1>
<p>If tokens are a currency, English speakers got a significantly better deal on it.</p>
<p>Petrov, La Malfa, Torr, and Bibi published <a href="https://arxiv.org/abs/2305.15425">"Language Model Tokenizers Introduce Unfairness Between Languages"</a> at NeurIPS 2023. They <a href="https://aleksandarpetrov.github.io/tokenization-fairness/">evaluated 17 tokenizers across 200+ languages</a> on FLORES-200, the standard multilingual parallel corpus. The single most cited number from that paper: the same translated sentence can produce <em>"differences up to 15 times"</em> in token count across languages, and the disparity persists even on tokenizers explicitly designed for multilingual support.</p>
<p><a href="https://www.artfish.ai/p/all-languages-are-not-created-tokenized">Yennie Jun's parallel study</a> across 52 languages and 2,033 messages quantified the everyday cost. English averaged 7 tokens per message. Spanish, French, and Portuguese came in at similar rates. Hindi and Bengali ran approximately 5× English. Armenian ran 9×. Burmese reached 72 tokens, roughly 10× English for the same sentence. Her summary: <em>"some languages require up to 10 times more tokens."</em></p>
<p>Newer tokenizers narrow the gap without closing it. Tamil's நீ ("you") <a href="https://www.njkumar.com/gpt-o-multilingual-token-compression/">was four tokens in <code>cl100k_base</code> and is a single token in <code>o200k_base</code></a>. Gemini's larger SentencePiece vocabulary handles CJK (Chinese, Japanese, Korean) noticeably better than the GPT-4 generation did. But the underlying training distribution is still English-dominant, and the structural penalty has not been engineered away.</p>
<p>What this means in practice: if your customer base is Hindi-speaking and your model uses an English-trained tokenizer, you are paying roughly four to five times what an equivalent English workload costs you, for content of equivalent meaning. The vendor did not charge you more per token. The exchange rate did the charging.</p>
<h1>The AI token fees you cannot see on the menu</h1>
<p>Once you accept that the token is the currency and the rate is the vendor's, the rest of the LLM bill becomes simultaneously more legible and stranger.</p>
<p><strong>Reasoning tokens.</strong> Newer models think before they answer, and the thinking counts. OpenAI's o-series, <a href="https://api-docs.deepseek.com/news/news260424">DeepSeek's V4</a> in its thinking mode, Anthropic's extended-thinking models (Opus 4.7 by default now runs its <code>xhigh</code> effort tier in Claude Code), and Gemini's thinking modes all generate internal chain-of-thought that gets billed at the output rate. <a href="https://developers.openai.com/api/docs/guides/reasoning">OpenAI exposes a count of reasoning tokens</a> in <code>output_tokens_details.reasoning_tokens</code>, though the actual chain-of-thought is summarized or hidden. <a href="https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-7">Anthropic in Opus 4.7 omits thinking content from the response by default</a>, but the count is billed whether or not you request a summary. A 10,000-token reasoning budget on <a href="https://openai.com/index/introducing-gpt-5-5/">GPT-5.5 at $30/M output</a> costs thirty cents before the user sees a word. Most teams running translation or classification through reasoning models are paying many times what they should because nobody turned thinking off.</p>
<p><strong>Caching, which sometimes is not a discount.</strong> OpenAI applies cache discounts automatically, up to 90% off on cached input, with no write premium and no code changes required. Anthropic uses explicit <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching"><code>cache_control</code> markers</a>: reads are 10% of base input (the deepest discount on the market), but writes cost 1.25× base on a five-minute TTL or 2× base on a one-hour TTL. <a href="https://platform.claude.com/docs/en/about-claude/pricing">Anthropic's own pricing page</a> says the math amortizes after one cache hit on the five-minute tier, or two on the hour-long one. But if your prefix, the stable front of the prompt you mark for caching, gets written and rarely re-read, caching costs you more than not caching. Gemini layers in a <a href="https://ai.google.dev/gemini-api/docs/pricing">per-hour storage fee</a> ($4.50 per million tokens cached per hour on 3.1 Pro), and the cache-read rate also doubles above 200K context, so the long-context cliff applies to caching too.</p>
<p><strong>Context cliffs.</strong> Most vendors charge a flat per-token rate across their full context window. A few do not. Gemini 3.1 Pro is $2 in / $12 out per MTok up to 200K, then $4 in / $18 out above. <a href="https://openai.com/api/pricing/">OpenAI's GPT-5.5 jumps to $10 in / $45 out above 272K input tokens</a>. Anthropic's Opus 4.6 and 4.7 are flat across their 1M window, with one caveat: there is a 1.1× surcharge if you request US-only inference routing. A RAG pipeline whose prompt-length distribution flirts with these thresholds can change cheapest-vendor depending on the day's typical input length.</p>
<p><strong>Batch.</strong> This is the one place the price card stops misrepresenting your actual cost. <a href="https://ai.google.dev/gemini-api/docs/batch-api">Google's batch API is half the standard rate</a>; OpenAI and Anthropic match. If your workload tolerates async latency, batch is the single most impactful switch you can make, more than swapping vendors, and usually more than switching models within a vendor. The number of production pipelines that are eligible for batch and not using it is alarming.</p>
<h1>What the LLM price card actually tells you</h1>
<p>Pull all of this together and the dollar-per-million-token figure on a vendor's pricing page tells you exactly one thing: the dollar cost of one million units of that vendor's specific currency at this moment for the specific model variant and inference region and effort tier and TTL choice you picked. It does not tell you the cost of doing your work. The translation from "currency" to "work" sits inside the tokenizer, the language mix of your content, your reasoning-token policy, your cache hit pattern, your batch share, and your prompt-length distribution against context cliffs.</p>
<p>The honest unit for cross-vendor comparison is not cost-per-token. It is cost-per-task: what you pay, end-to-end, for a unit of output your users would accept. The formula is:</p>
<p><em>cost_per_task = (price_per_token × tokens_per_request × (1 + reasoning_overhead) × (1 − cache_hit_rate × cache_discount) × (1 − batch_share × 0.5)) ÷ task_success_rate</em></p>
<p>Every term is measurable. Token count comes from each vendor's official counter. Reasoning overhead comes from the usage block on each response. Cache hit rate and batch share come from your own logs. Task success rate comes from your eval. The headline $/MTok is one term on the right side, not the answer to the equation.</p>
<p>Cost is not the only thing that moves. More tokens means a longer sequence, which brings more latency, more KV-cache memory, and a higher chance of crossing the 200K/272K context cliffs in ways that can change how an agent loop behaves. Tokenizer inflation lands in your latency and memory budgets, not just the bill.</p>
<h1>The state of the major LLM currencies, May 2026</h1>
<p>Here is what each vendor is actually doing under their published rate card, in the dimensions that matter for real bills:</p>
<table>
<thead>
<tr>
<th><strong>Vendor</strong></th>
<th><strong>Can you count tokens locally?</strong></th>
<th><strong>How stable is the tokenizer across versions?</strong></th>
<th><strong>Caching</strong></th>
<th><strong>Long-context cliff</strong></th>
<th><strong>Batch</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>OpenAI</strong></td>
<td>Yes: tiktoken is open</td>
<td>Changed once: GPT-4 → GPT-4o (cl100k → o200k)</td>
<td>Automatic, ≤90% off, no write premium</td>
<td>Flat to 1M on GPT-4.1; 272K cliff on GPT-5.5 (≈2× input, 1.5× output)</td>
<td>50% off</td>
</tr>
<tr>
<td><strong>Anthropic</strong></td>
<td>No: only via count_tokens API</td>
<td>Changed 4.6 → 4.7: 1.0–1.35× per Anthropic, 1.46× measured by Willison</td>
<td>Explicit cache_control; 0.10× reads, 1.25–2× write premium</td>
<td>Flat to 1M; 1.1× surcharge on US-only inference</td>
<td>50% off</td>
</tr>
<tr>
<td><strong>Google Gemini</strong></td>
<td>Partial: Gemma 3 SentencePiece (262,144 vocab) is published</td>
<td>Differs across 1.5 / 2.x / 3.x lines</td>
<td>Explicit + per-hour storage fee; cache reads also double above 200K</td>
<td>2× input, 1.5× output above 200K on 3.1 Pro</td>
<td>50% off</td>
</tr>
<tr>
<td><strong>DeepSeek</strong></td>
<td>Yes: BBPE (byte-level BPE) published</td>
<td>V2 → V3 expanded 100K → 128K; V4 added dual thinking/non-thinking modes</td>
<td>Automatic disk cache, no write premium</td>
<td>Flat</td>
<td>Off-peak discount</td>
</tr>
<tr>
<td><strong>Meta Llama</strong></td>
<td>Yes: tokenizer.json ships with the model</td>
<td>Llama 2 → 3: 32K → 128,256</td>
<td>Host-dependent (Bedrock, Together, Groq differ)</td>
<td>Host-dependent</td>
<td>Host-dependent</td>
</tr>
<tr>
<td><strong>Mistral</strong></td>
<td>Yes</td>
<td>SentencePiece → Tekken (NeMo, Pixtral)</td>
<td>Host-dependent</td>
<td>Host-dependent</td>
<td>Host-dependent</td>
</tr>
</tbody></table>
<p>The vendors split into two groups. Open-tokenizer providers (OpenAI, DeepSeek, Meta, Mistral) let you compute cost client-side before you send the request, which is useful for budgeting, useful for routing, and useful when you are trying to A/B against another model. Closed-tokenizer providers (Anthropic, Gemini in part) require a round-trip to find out what the request will cost. That asymmetry is itself a feature of the pricing, even though it does not appear on any pricing page.</p>
<h1>Auditing your own AI currency exposure</h1>
<p>The practical version of this post is a worksheet, not a checklist. Sit with your team and answer:</p>
<ol>
<li><p><strong>What does your token actually buy?</strong> Take 50–100 real prompts from production logs. Run each through every candidate vendor's official token counter. Compare the counts. A 20% gap on your real content is normal; a 50% gap on non-English content is normal. Now multiply each count by each vendor's $/MTok and look at the result. This is the real per-call cost, not the price card cost.</p>
</li>
<li><p><strong>How much are you paying to think?</strong> For every reasoning-capable model you use, pull the reasoning-token count from the usage block. Multiply by output price. If a non-trivial fraction of your bill is thinking tokens on workloads that do not need them, such as translation, classification, extraction, or short Q&amp;A, turn thinking off. This is almost always the largest single optimization available.</p>
</li>
<li><p><strong>Does caching cost you or save you?</strong> Pull the actual ratio of cache writes to cache reads from your logs. On Anthropic, if your prefix gets written more often than it gets read, the write premium is making things worse, not better. On Gemini, work out whether the per-hour storage fee on rarely-hit caches is worth the discount on the hits.</p>
</li>
<li><p><strong>Where in your prompt-length distribution do the cliffs sit?</strong> Histogram your input lengths against 200K (Gemini) and 272K (GPT-5.5). If the 90th percentile is anywhere near those numbers, you are paying tier-2 rates more often than you realize.</p>
</li>
<li><p><strong>What fraction of your traffic could be batch?</strong> If 30% of your work is async-tolerant and you are not batching it, you are leaving ~15% of your total bill on the table.</p>
</li>
<li><p><strong>What's your real success rate per dollar?</strong> A cheaper-per-token model that fails your eval 20% more often is more expensive in production. Build the cost-per-accepted-task number. Reorder vendor preferences accordingly.</p>
</li>
</ol>
<h1>Why this state of affairs persists</h1>
<p>It is tempting to read all of the above as vendors being deliberately opaque. Mostly, they are not. The Opus 4.6 → 4.7 tokenizer change was, on the merits, the right engineering trade for downstream quality. Anthropic's cache write premium reflects real storage and warm-cache costs. Gemini's 200K cliff is honestly disclosed. OpenAI's automatic caching is genuinely user-friendly. Every individual decision makes sense on its own.</p>
<p>What is missing is a market norm requiring vendors to publish their tokenizers, announce changes, and standardize the comparison unit. Until that norm exists, and there is no commercial incentive for any vendor to ship it unilaterally, the dollar-per-million-token figure on a pricing page will continue to be the most quoted and least informative number in the industry.</p>
<p>The fix lives on the buyer side. Track cost-per-task, not cost-per-token. Tokenize your real prompts before you migrate. Route by workload, not by vendor. Audit reasoning overhead like you audit any other line item. Treat the price card as one input to a model of your true unit economics, not the model itself.</p>
<p>And when a thread titled "Opus 4.7 to 4.6 Inflation is ~45%" climbs the front page of Hacker News on the day after a model launch, check the tokenizer before you check the price card.</p>
<img src="/blog/the-great-token-heist-of-26/78d92d86-be82-4f8e-bad2-b499db01ede0.png" alt="" style="display:block;margin:0 auto" />

<hr />
<p><em>— Written from the Altimate team. We build</em> <a href="https://altimate.ai/"><em>Altimate-Code</em></a><em>, an agentic data engineering platform for enterprises. If you're working through this kind of vendor economics for your own stack, we'd like to compare notes.</em></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/the-great-token-heist-of-26/a164d003-f725-473b-a6e6-a026ab05d821.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>The Correctness Layer</title>
    <link>https://altimate.ai/blog/the-correctness-layer-in-ade</link>
    <guid isPermaLink="true">https://altimate.ai/blog/the-correctness-layer-in-ade</guid>
    <pubDate>Wed, 20 May 2026 17:32:37 GMT</pubDate>
    <dc:creator>Syed Haider</dc:creator>
    <dc:creator>Surya Iyer</dc:creator>
    <category>agentic AI</category>
    <category>data-engineering</category>
    <category>altimateAI</category>
    <description>We started altimate-code with one goal: build a harness that data engineers could actually trust with their pipelines and platforms. The first thing that became clear is that LLMs are the wrong tool f</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/the-correctness-layer-in-ade/1871c39e-0eee-4e5f-ba3c-fbf6eb835a79.jpg" alt="The Correctness Layer" /></p>
<p>We started <a href="https://www.altimate.sh/">altimate-code</a> with one goal: build a harness that data engineers could actually trust with their pipelines and platforms. The first thing that became clear is that LLMs are the wrong tool for half of that job. Two queries either are or are not semantically equivalent. A lineage edge either does or does not exist. A row-level diff is either correct or not. None of those are creative questions, and a probability distribution is the wrong answer to any of them.</p>
<p>Over the past year, we have built a three-layer architecture that puts the LLM in charge of the work it is good at (strategy, intent-parsing, code generation) and a deterministic Rust and TypeScript stack underneath for everything that has to be reproducible. The split (detailed later) is what gets us to the top of the ADE and the <a href="https://ucbepic.github.io/DataAgentBench/">DAB</a> benchmarks, and more importantly, what makes the result repeatable on someone else's hardware.</p>
<p>This post walks through how the split actually works: where the boundary sits, the three operations we moved out of the model entirely, and what thousands of structured benchmark traces taught us about where agents actually fail.</p>
<h2>LLMs are probability distributions</h2>
<p>Run the same prompt through the same model twice, and you'll get two different answers. That's not a bug. It's the substrate. Language models sample from a probability distribution every time they generate a token, and the distribution is shaped — sometimes broadly — by sampling temperature[1], prompt-cache state, and the internal nondeterminism of large batched inference on shared hardware[2].</p>
<p>For creative work, this is exactly what you want. Drafting a SQL query, summarizing a result, recovering from an unexpected error — these are open-ended tasks with many acceptable answers, and probabilistic output is what makes the model useful.</p>
<p>For correctness, it's a liability. "Are these two queries semantically equivalent?" has one right answer. "What columns does this output project from this source?" has one right answer. "Are these two tables byte-equal?" has one right answer. When a probabilistic system answers a deterministic question, you can't cache the answer (it might be different next time), you can't debug it (a single sample tells you nothing about the distribution), and you can't benchmark it (a single pass-rate is a coin flip away from a different number).</p>
<h2>What this looks like on a real benchmark</h2>
<p>We took one task off the <a href="https://github.com/dbt-labs/ade-bench">ADE benchmark</a>, a dbt refactor called <code>asana004</code>, and ran it through altimate-code three times with the same model, the same prompt, and the same starting state. The agent passed it once and failed it twice. Across the three runs, dbt's test counts came back as 6/6, then 4/6, then 5/6.</p>
<p>If you are building a data-engineering agent, that is the problem you have to design around. You cannot trust a system whose output is intrinsically random. You cannot cache it. You cannot reproduce it. You cannot debug it. And you cannot reliably benchmark it.</p>
<h2>The comfortable go-to (but wrong) answer</h2>
<p>The instinct is to make the model itself more deterministic. Lower the temperature. Tighten the prompts. Introduce multi-agent voting. Run test-time consensus across N samples. Vendors in the data space are responding to this demand, and their responses make sense on some level. Temperature=0 is easy (provides marginal repeatability at the cost of much of the agent's ability to explore or recover from mistakes), ensemble voting is well-understood, and prompt engineering keeps getting better.</p>
<p>This works, partially. Lower temperature reduces variance but does not eliminate it. Multi-agent voting trades dollars for variance reduction but never reaches zero. None of it changes the fundamental shape of the problem. The model is a probability distribution, and you are sampling from it.</p>
<h2>So stop fixing the model</h2>
<p>The LLM should stay out of the correctness layer.</p>
<p>That is the bet behind altimate-code. The LLM stays in charge of strategy, intent-parsing, and code generation, which are the genuinely creative parts of the work. Everything else runs in a deterministic Rust and TypeScript layer underneath: SQL validation, schema diffing, query equivalence, lineage extraction, cross-database join inference, data-parity diffing. The agent does not decide whether two queries are equivalent. It calls a function that proves they are.</p>
<p>I keep coming back to this framing because it is the only one I have seen that survives contact with a real benchmark. Once you have watched the same prompt produce three different answers, you stop wanting the model to be more reliable. You start wanting it to be less involved.</p>
<blockquote>
<p><em>Once you have watched the same prompt produce three different answers, you stop wanting the model to be more reliable. You start wanting it to be less involved.</em></p>
</blockquote>
<h2>Three layers</h2>
<p>altimate-code's architecture has three layers. The decision that matters most is where the boundary between them sits.</p>
<img src="/blog/the-correctness-layer-in-ade/60f9ccf1-3568-45c0-a913-2406eb75fd21.png" alt="" style="display:block;margin:0 auto" />

<p>The <strong>deterministic core</strong> is a Rust library (<code>altimate-core</code>) that exposes 34 SQL operations as pure functions over abstract syntax trees and schemas. It parses, validates, transpiles, fingerprints, checks equivalence, diffs schemas, classifies PII, extracts column lineage, and diffs rows across warehouses. Every operation runs sub-millisecond. Our benchmark battery validates 1,000 SQL queries in 30 ms and lints 1,000 queries in 250 ms. All of it is reproducible. All of it is zero-cost at the LLM API layer because it never touches the model. The engine carries 5,700+ Rust tests, runs on a single sqlparser-based AST representation, and targets 34 SQL dialects, from Postgres and Snowflake to Trino and TSQL.</p>
<p>The <strong>deterministic harness</strong> is the TypeScript code that runs the agent. A dispatcher maintains a registry of native handlers. When the agent calls <code>altimate_core.transpile</code>, the dispatcher routes the call to compiled Rust via napi-rs bindings, not to the model. Skills (encoded playbooks) prescribe step orderings. Helpers like dialect-aware identifier quoting prevent whole classes of "the model generated almost-correct SQL" failures.</p>
<p>The <strong>probabilistic agent</strong> is the LLM. It reads task descriptions, plans, picks tools, writes drafts, summarizes results, and recovers from failures. It sits in the creative layer, not the correctness layer.</p>
<p>The agent does not always know which layer it is calling into. But it always can know. A <code>hasNativeHandler</code> check classifies a tool call as deterministic or not before it runs. That asymmetry is most of the value.</p>
<p>Consider what happens when the agent calls <code>altimate_core.track_lineage</code>. The tool wrapper packages the arguments. The dispatcher looks up the handler registered for that method name. The handler normalizes the agent-supplied schema, accepting either the flat <code>{table: {col: TYPE}}</code> shape or the nested <code>SchemaDefinition</code> shape, and converts both to a canonical form before passing through. The napi-rs binding calls into compiled Rust. The Rust engine builds the lineage graph and returns it. The tool formats the output for the agent. From the agent's perspective, it called a tool and got back lineage. From the architecture's perspective, every step is deterministic, including the schema normalization, which the harness does, not the model.</p>
<img src="/blog/the-correctness-layer-in-ade/fffbede3-6ad9-46d4-ad55-a4ccc5307558.png" alt="" style="display:block;margin:0 auto" />

<h2>What this looks like in practice</h2>
<p>I will walk through three concrete operations, because adjectives do not earn the claim.</p>
<p>Take two queries written differently but doing the same thing:</p>
<pre><code class="language-sql">-- Writer A
SELECT id FROM users
WHERE status = 'active'
  AND created &gt; NOW() - INTERVAL 30 DAY

-- Writer B
SELECT id FROM users
WHERE created &gt; DATE_SUB(NOW(), INTERVAL 30 DAY)
  AND status = 'active'
</code></pre>
<p><code>altimate_core.checkEquivalence</code> proves these are semantically identical without running either of them. The comparison happens on parsed ASTs against the provided schema. It handles predicate reordering, equivalent date-arithmetic functions, and identical column projection. The result is a boolean plus a confidence score, not a sample of an LLM's opinion. Downstream, that means refactor verification, migration safety checks, and regression tests that confirm a query's behavior did not change. None of it requires a live database or a model that "looks at" the queries.</p>
<p>Dialect translation is the same story. <code>transpile(sql, fromDialect, toDialect)</code> takes a Snowflake query and produces a BigQuery one (or BigQuery to Postgres, or Postgres to Databricks) via <code>sqlparser-rs</code> and dialect-specific AST transforms. It runs sub-millisecond. The agent never has to memorize that Snowflake's <code>IFF(cond, a, b)</code> becomes <code>CASE WHEN cond THEN a ELSE b END</code> in ANSI dialects. We have measured the LLM-direct alternative. The failure mode is not "wrong output." It is almost-right output that compiles in dev and breaks in prod when an edge-case function shows up. Determinism here is not about speed. It is about coverage. The AST transform handles every case the parser handles, not every case the model happens to have seen in training.</p>
<p><code>schemaFingerprint(schema)</code> returns a SHA-256 hash of a serialized schema. That is the entire interface. The hash is what makes caching trustable. When the agent is validating many queries against a large schema, we compute the fingerprint once and use it as a cache key. Identical schemas produce identical hashes, and the cache hits. An LLM-derived "is this schema the same?" cannot offer that guarantee. A model might say "yes" twice and "no" the third time, and you would have to debug whether the third answer was the wrong one. The fingerprint also acts as the index for progressive context compression. The core exposes five disclosure levels: fingerprint-only, table list, column names (the default), full detail for relevant tables only, and the complete schema - and the agent picks the level it needs for the question at hand. The selection is deterministic, the cache key is deterministic, and nothing about either step is the LLM's opinion of "is this schema close enough?"</p>
<p>Reliability and performance turn out to be the same lever pulled twice. Determinism is what makes the cache safe. The cache is what makes the agent fast. You cannot get the second without the first.</p>
<h2>Case study: cross-database join inference</h2>
<p>The cleanest illustration of this principle is a tool we shipped in late April 2026. <a href="https://github.com/AltimateAI/altimate-code">altimate-code</a> is often connected to several warehouses at once (Snowflake, BigQuery, Postgres), and the agent needs to suggest cross-database joins. One warehouse calls an entity <code>customer_42</code>. Another calls it <code>cust_42</code>, or <code>c-42</code>, or <code>42</code>. Naming and formatting disagree, so naive column-name matching fails.</p>
<p>A pure-LLM approach to this is straightforward to describe and unreliable to ship. You prompt the model with the schemas and ask "which columns join across these DBs?" It works on the cases the model has seen. It hallucinates plausible-but-wrong matches on the cases it has not. Different runs return different rankings.</p>
<img src="/blog/the-correctness-layer-in-ade/180cf068-ad07-4493-90b9-5261db1239dc.png" alt="" style="display:block;margin:0 auto" />

<p>The deterministic version is about 400 lines of TypeScript. The algorithm is small enough to summarize:</p>
<ol>
<li><p>From each connection, sample ~50 string values per column.</p>
</li>
<li><p>Compute the longest common prefix per column, trimmed back to the last <code>_</code>, <code>-</code>, or <code>:</code> separator. So <code>["businessid_42", "businessid_43", …]</code> produces prefix <code>"businessid_"</code>. Sequences without a separator are rejected.</p>
</li>
<li><p>For each pair of columns from different databases, require distinct non-empty prefixes (so the prefix actually distinguishes the two columns), strip the prefixes, and compute the set intersection of suffixes.</p>
</li>
<li><p>Emit a candidate when the suffix overlap is non-empty. Rank by overlap size, then by <code>overlap / min(left, right)</code>.</p>
</li>
</ol>
<p><code>businessid_42</code> on one DB and <code>businessref_42</code> on another both reduce to suffix <code>42</code>. The algorithm pairs them with score 1.0 and reports the rule as "shared suffix after stripping distinct prefixes."</p>
<p>The function that computes the common prefix is fewer than 30 lines. It walks character-by-character and trims back to the last separator. Identical inputs produce identical outputs, every time, in any order, on any machine. We can ship the algorithm to a customer and tell them exactly what will happen.</p>
<h2>Case study: column lineage with depth tiering</h2>
<p>Lineage is the question of where each output column comes from. Given a query with joins, CTEs, and expressions like <code>SUM(o.amount + o.tax)</code>, you need to know which upstream columns flow into each output. An LLM can answer this question in plain English. It cannot answer it precisely enough to chain operations on. Agents that act on lineage need exact edges, not summaries.</p>
<p><code>altimate_core.column_lineage</code> does this as an AST walk. Each output column gets a list of source columns plus a transformation lens: direct projection, function call, expression, or aggregation. The walk is deterministic by construction. Subqueries and CTEs are inlined. Window functions decompose into their partition and order clauses. CASE expressions report all branches as sources.</p>
<p>The piece worth featuring is the <em>depth tiering</em>. The same engine exposes three modes:</p>
<ul>
<li><p><strong>Basic</strong>: direct source-target edges only, with minimal context.</p>
</li>
<li><p><strong>Deep</strong>: adds transformation lenses (expression, function, aggregation), confidence scores, and the internals of every CTE the lineage flows through.</p>
</li>
<li><p><strong>Full</strong>: transitive closure across multi-query chains, plus indirect dependencies from <code>WHERE</code>, <code>JOIN</code>, and <code>GROUP BY</code> predicates that affect row selection.</p>
</li>
</ul>
<p>The agent picks the depth it needs for the question at hand. The classification of what counts as "basic" versus "deep" is encoded. It is not an LLM call disguised as one. The pattern repeats: every level of detail an agent can ask for is a level the engine knows how to produce, and the choice between them is a parameter, not a guess.</p>
<p>The same principle controls the output format. Lineage, like every operation in altimate-core, ships with two formatters: a verbose one for humans, and a compact one optimized for an agent's context window. Compact is the default. The agent gets a headline token (<code>LINEAGE | 5 cols, 3 tables, depth=basic</code>) followed by structured <code>column &lt;- source</code> rows it can parse without spending tokens on prose. Depth chooses how much detail; the format chooses how that detail is encoded; both compound across a trajectory of hundreds of tool calls.</p>
<h2>Case study: data parity</h2>
<p>A different shape of problem: prod was migrated to a new warehouse, and we need to know whether the rows match.</p>
<p>The naive answers are bad. You write a 200-line custom SQL diff query and hope you covered the edge cases, or you ask an LLM to "compare these two tables" and get an unactionable summary.</p>
<img src="/blog/the-correctness-layer-in-ade/72445e75-27a6-4720-9c09-cc24d6caef39.png" alt="" style="display:block;margin:0 auto" />

<p>The engine implements two complementary algorithms. <strong>HashDiff</strong> uses bisection plus checksums for cross-database diffs. It partitions both tables, checksums each segment, recursively bisects any segment whose checksums disagree, and terminates at the row level on exactly the segments that contain mismatches. The bisection lets it pinpoint the exact rows that differ instead of scanning every row, and the module ships with 303 dedicated tests covering every dialect pair we support. <strong>JoinDiff</strong> uses a same-database <code>FULL OUTER JOIN</code> for when both tables live in the same warehouse. The cost characteristics differ. The correctness guarantee is the same.</p>
<p>The engine ships with a cooperative state-machine API. It emits the SQL it wants executed, the caller runs it, and the engine steps forward based on the result. There is no point in the loop where the engine guesses, or where its behavior depends on which LLM is in front. Given identical inputs, the diffs come out identical, every time.</p>
<p>"<em>Are these two tables byte-equal?</em>" is the antithesis of a creative task.</p>
<h2>Smaller wins, in the harness</h2>
<p>So far the story has been about the Rust core. The TypeScript harness gets the same treatment, and the wins are smaller per-instance but they compound.</p>
<p>A single function called <code>quoteIdentForDialect</code> holds the truth about identifier quoting across our supported warehouses. MySQL gets backticks, T-SQL gets brackets, and everything else gets ANSI double quotes. The LLM never has to remember which is which, because it never builds quoted SQL directly. It passes column names through tools that route through <code>quoteIdentForDialect</code>. That is not a clever optimization. It is a category of failure removed from the system. The same pattern applies to <code>EXPLAIN</code>-plan retrieval. Postgres has <code>EXPLAIN (ANALYZE, BUFFERS)</code>. Snowflake has <code>EXPLAIN USING TEXT</code>. BigQuery has no <code>EXPLAIN</code> statement at all, and you read plans from job metadata. A ~50-line decision table maps each warehouse to its plan-retrieval mechanism. The agent does not ask the model "what is the BigQuery EXPLAIN syntax?" because a tool already knows.</p>
<p>Skills are altimate-specific procedures encoded in markdown. The <code>dbt-develop</code> skill prescribes a four-step workflow: plan (check the layer and naming conventions), discover (use schema-search tools, read existing YAML), write (generate SQL with validated joins), and validate (call <code>altimate_core_validate</code>, then <code>column_lineage</code>, then <code>dbt build</code>). The skill does not replace the LLM. It constrains where the LLM is creative and where the harness is prescriptive. Our trace data shows skill-driven sessions complete in fewer turns and with fewer tool errors than ad-hoc sessions on the same task.</p>
<p>None of these are individually dramatic. Cumulatively they are the difference between an agent that almost works and one you can deploy.</p>
<h2>What thousands of session traces taught us</h2>
<p>We ran the ADE-Bench DuckDB benchmark against altimate-code and captured structured traces for every session. Our benchmark topping score was 74.4%.<a href="2">[2]</a> The traces are where the interesting story lives.</p>
<p>Failure has three distinct causes, and they require three different responses.</p>
<p>The first cause is stochastic LLM noise. Two airbnb tasks (<code>airbnb005</code>, <code>airbnb006</code>) failed the original baseline but then passed all three reruns. <code>asana004</code> (the task from the opening) passed once out of three. The inputs are the same, the outputs differ, and the cause is intrinsic to the model. There is nothing to fix here except the model.</p>
<p>The second cause is deterministic capability gaps. <code>asana003</code> failed at exactly 16 of 17 dbt tests, every single time across reruns. Same failure mode every time, with the same dbt-test count. The agent's output has a stable bug we can investigate and fix.</p>
<p>The third cause is bench-fixture bugs. Three airbnb tasks (<code>airbnb001</code>, <code>airbnb002</code>, <code>airbnb008</code>) failed reproducibly, but the root cause was a pre-existing bug in the bench's own dbt incremental models: a broken <code>is_incremental()</code> filter that collapses the date series to a single row, so the <code>LAG</code> window function in the MoM/WoW aggregation returns <code>NULL</code> on rerun and overwrites the correct first-run values. This is not an altimate-code problem. The maintainers shipped a test-setup workaround in dbt-labs/ade-bench#106, but the model SQL itself is still broken — fix proposed in <a href="https://github.com/dbt-labs/ade-bench/pull/145">dbt-labs/ade-bench#145</a>.</p>
<p>From the outside, all three look identical. The test failed. Only the deterministic substrate (structured traces, reproducible reruns, exact dbt-test counts) lets us separate them. Without that, we would be guessing about what is actually wrong, and our improvement work would be aimed at the wrong target.</p>
<h2>Where the market is</h2>
<p>Most coding agents in the field are general-purpose. Cursor, Cline, Claude Code, Codex, and GitHub Copilot Workspace all sit in that category. They are built for the generic developer-with-a-text-editor case. When a data engineer uses them to write a Snowflake query or refactor a dbt model, the tools treat SQL like any other code. Text goes in, text comes out, and the model decides. There is no deterministic substrate for the data-specific operations because there does not need to be one for general coding.</p>
<p>The data-native AI products (dbt Cloud's AI features, in-warehouse LLMs like Snowflake Cortex) are closer to the right surface area, but they are still primarily LLM wrappers with a different UI. They generate SQL. They do not prove SQL.</p>
<p>Our bet is that for data engineering specifically, the LLM-as-creative-layer / code-as-correctness-layer split is the right architecture, and that the deterministic infrastructure is where the actual moat lives. Models will get better. APIs will get cheaper. Prompt techniques will improve. None of that changes the calculus on whether two queries are semantically equivalent, or whether a cross-warehouse data diff is correct. Those are facts about code and data, decidable by code that operates on code and data.</p>
<p>altimate-code currently sits at number one on the <a href="https://www.altimate.sh/benchmarks">ADE benchmark</a>, ahead of Claude Code, Cortex Code CLI, and dbt Labs, by a wide margin. It also recently scored #1 on the <a href="https://ucbepic.github.io/DataAgentBench/">Berkeley EPIC Data Lab DAB</a> (Data Agent Benchmark)</p>
<h2>What is still LLM territory</h2>
<p>It would be dishonest to claim we replaced the LLM. We did not, and we will not. The LLM still owns intent-parsing ("refactor the <code>asana__project</code> model into an intermediate one that…"), code generation, description-writing for dbt model YAML, and strategy under uncertainty. When a build fails for reasons that are not immediately classifiable, the model is what figures out the next move.</p>
<h2>What's next</h2>
<p><em><strong>Comparative trace analysis across models</strong></em>. Sonnet, Opus, DeepSeek v4 pro, Kimi K2, and Qwen 2.5 Coder all run through the same altimate-code stack on the same benchmarks. What we don't yet have is a systematic comparison of how they differ on data-engineering tasks — which failure modes are model-specific vs architecture-specific, which models pair best with which skills, where the cost-quality frontier sits per task category. The traces are captured; we’ll share the analysis soon.</p>
<p><em><strong>Harness resilience</strong></em>. The same trace data surfaces a handful of harness-side next moves. We are making the agent loop resilient to truncated model outputs from streaming providers. We are adding a per-generation timeout so a hung request does not tie up a worker for 25 minutes. We are detecting when the agent has fallen into a same-tool-same-argument loop and forcing a replan. Each one is a place where the harness can be more deterministic about how it handles a probabilistic model.</p>
<p><em><strong>Cost / quality frontier mapping</strong></em>. Our DeepSeek v4 pro run on DAB scored 0.5693 stratified Pass@1 for $9 of inference, ahead of the then benchmark leader Pi's Opus 4.6 submission — is one data point in a larger frontier. We’re in touch with DAB maintainers to add this run to the leaderboard. The natural follow-up is systematic: across the model lineup we already run through altimate-code, at what cost does each model fall below a quality threshold, broken out by task category (SQL refactor, dialect translation, lineage extraction, cross-DB joins)? The architecture is model-agnostic; the right backbone for a given customer workload may be category-dependent.</p>
<h2>Conclusion</h2>
<p>The claim is narrower than "no LLM." It is that the LLM stays out of correctness. The probabilistic layer handles probabilistic work. The deterministic layer handles deterministic work. The boundary is where the payoff lives.</p>
<p>Probabilistic models are a remarkable substrate for the things they are good at: language, intent, creativity. They are a poor substrate for proof, equivalence, and reproducibility. The architectural question for any agent in this space is not "can we use the LLM for X?" It is <em>"should we, and if not, what should we use instead?"</em></p>
<p>For the data-engineering work altimate-code does, the answer is the correctness layer underneath: a deterministic core in Rust, a deterministic harness in TypeScript, with the LLM kept exactly where it belongs.</p>
<p><a href="1">[1]</a>: <a href="https://platform.claude.com/docs/en/api/messages/create#create.temperature">Claude API Docs</a></p>
<p><a href="2">[2]</a>: <a href="https://thinkingmachines.ai/blog/defeating-nondeterminism-in-llm-inference/">Defeating Nondeterminism in LLM Inference</a></p>
<p><em>altimate-code is an open source project:</em> <a href="http://github.com/AltimateAI/altimate-code"><em>github.com/AltimateAI/altimate-code</em></a><em>.</em><br /><em>If you are building in this space and want to compare notes, reach out by email at</em> info-at-altimate.ai*.*</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/the-correctness-layer-in-ade/1871c39e-0eee-4e5f-ba3c-fbf6eb835a79.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>Blast Radius Analysis Using Altimate Code</title>
    <link>https://altimate.ai/blog/blast-radius-analysis-using-altimate-code</link>
    <guid isPermaLink="true">https://altimate.ai/blog/blast-radius-analysis-using-altimate-code</guid>
    <pubDate>Mon, 18 May 2026 13:22:09 GMT</pubDate>
    <dc:creator>Muhammad Anas Farooqui</dc:creator>
    <category>altimate-code</category>
    <category>Data pipelines</category>
    <category>dbt</category>
    <category>data-engineering</category>
    <category>snowflake</category>
    <category>devtools</category>
    <category>#ai-tools</category>
    <description>What is Blast Radius
Blast radius refers to the potential extent of damage.
For example, before you knock down a wall in your house, you want to know if there&apos;s plumbing behind it, electrical wiring w</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/blast-radius-analysis-using-altimate-code/872f1689-fd5d-494d-b1b9-cf001d92f029.png" alt="Blast Radius Analysis Using Altimate Code" /></p>
<h1>What is Blast Radius</h1>
<p>Blast radius refers to the potential extent of damage.</p>
<p>For example, before you knock down a wall in your house, you want to know if there's plumbing behind it, electrical wiring within it, or if it's holding up the floor above.</p>
<p>Same idea with data. Before you rename a column, change a formula, or update a filter, you need to know what depends on it. That could include downstream models, dashboards, reports, or other workflows.</p>
<hr />
<h1>Need for Blast Radius Analysis</h1>
<p>Often when you rename a column and push it to production, everything seems fine. Two days later, finance pings you on Slack: the weekly revenue dashboard has been broken since Tuesday.</p>
<p>You dig in. The column you renamed was referenced in three other models. One of those models feeds a Tableau workbook. That field is the denominator in the revenue metric on the CFO's dashboard.</p>
<p>Nobody documented any of this. The dependencies existed in the relationships between systems, invisible until something broke. This is the blast radius problem.</p>
<p><a href="https://docs.altimate.sh/getting-started/">Altimate Code</a> fixes this. Before any change goes through, it maps out the full impact automatically. It produces a detailed blast radius report (what will break, what's safe, what needs someone to sign off) and also performs the changes.</p>
<p>I ran a workflow using Altimate Code to verify this.</p>
<hr />
<h2>The workflow: renaming <code>total_cents</code> to <code>gross_revenue_cents</code></h2>
<p>I ran this on my open-source <a href="https://github.com/altimateanas/ecommerce_demos">CartWave E-commerce dbt project</a>, a real analytics codebase with staging models, intermediate transformations, mart tables, and a semantic layer on Snowflake.</p>
<p><code>stg_orders</code> is a simple staging model that reads raw order data and explicitly picks the columns that are needed. The finance team wants us to rename <code>total_cents</code> to <code>gross_revenue_cents</code> to align with GAAP terminology.</p>
<h3>The prompt</h3>
<p><strong>I gave Altimate Code this prompt:</strong></p>
<blockquote>
<p><em>"Rename the column total_cents to gross_revenue_cents in stg_orders as the finance team wants to align with GAAP terminologies. Before performing the changes, show me the blast radius of the same."</em></p>
</blockquote>
<img src="/blog/blast-radius-analysis-using-altimate-code/80e6c164-2932-4c78-bc7e-cf795dc17933.png" alt="Altimate Code is an agentic harness for data engineering." style="display:block;margin:0 auto" />

<p><em>One column, one rename. It should have been straightforward, but it wasn't.</em></p>
<hr />
<h3>What Altimate Code did</h3>
<p>After receiving the prompt, Altimate Code ran through a series of steps before changing a single line of code. Here's what happened, in order.</p>
<p><a class="embed-card" href="https://youtu.be/Npf7fHK43-k">https://youtu.be/Npf7fHK43-k</a></p>

<hr />
<p><strong>Step 1: It loaded the</strong> <code>dbt-analyze</code> <strong>skill and scanned the project.</strong></p>
<p>Altimate Code started by tracing the dependencies. It read the model SQL, searched every file in the project for references to <code>stg_orders</code>, and checked YAML config files for column-level references.</p>
<p>Within seconds it found five files that depend on <code>stg_orders</code>:</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/9fdf62f6-a929-471d-98e9-a77ce73c98e3.png" alt="" style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th>#</th>
<th>File</th>
<th>What it is</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td><code>int_order_enriched.sql</code></td>
<td>Combines order data with customer info</td>
</tr>
<tr>
<td>2</td>
<td><code>int_customer_lifetime.sql</code></td>
<td>Calculates lifetime value per customer</td>
</tr>
<tr>
<td>3</td>
<td><code>mart_return_analysis.sql</code></td>
<td>Report table for analyzing returns</td>
</tr>
<tr>
<td>4</td>
<td><code>sem_orders.yml</code></td>
<td>Defines business metrics like "total revenue"</td>
</tr>
<tr>
<td>5</td>
<td><code>_staging.yml</code></td>
<td>Documents what each column means</td>
</tr>
</tbody></table>
<p>Five files depend on this model. But how many of them actually use the column we're renaming? That's the question that matters.</p>
<hr />
<p><strong>Step 2: It checked each file for column-level references to</strong> <code>total_cents</code><strong>.</strong></p>
<p>Altimate Code checked more than whether a file depended on <code>stg_orders</code>. It opened each downstream file and looked for direct references to <code>total_cents</code>.</p>
<p>Here's what it found:</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/c50f73df-6320-4fed-8fc1-a7d0d5a33a6d.png" alt="" style="display:block;margin:0 auto" />

<p><code>int_order_enriched.sql</code> – <strong>BREAKING</strong></p>
<p>Directly selects <code>orders.total_cents</code> on line 31:</p>
<pre><code class="language-sql">orders.total_cents,   -- directly uses the column we're renaming
</code></pre>
<p><strong>Explanation:</strong> This file asks for a column called <code>total_cents</code>. After the rename, that column won't exist anymore. The query will fail.</p>
<p><code>int_customer_lifetime.sql</code> – <strong>BREAKING</strong></p>
<p>Sums <code>total_cents</code> across all orders on line 22:</p>
<pre><code class="language-sql">sum(total_cents) as lifetime_revenue_cents,  -- adds up all order values
</code></pre>
<p><strong>Explanation:</strong> Same problem. The column disappears, the math breaks.</p>
<p><code>mart_return_analysis.sql</code> – <strong>SAFE</strong></p>
<p>This one depends on <code>stg_orders</code> but only uses <code>customer_id</code> and <code>order_date</code>:</p>
<pre><code class="language-sql">orders.customer_id,   -- doesn't touch total_cents
orders.order_date,    -- doesn't touch total_cents
</code></pre>
<p><strong>Explanation:</strong> It never references the renamed column. No changes needed.</p>
<p><code>sem_orders.yml</code> <strong>(semantic layer)</strong> – <strong>BREAKING</strong></p>
<p>Two metric definitions reference <code>total_cents</code> by name in their formulas:</p>
<pre><code class="language-yaml">measures:
-name: total_revenue_cents
agg: sum
expr: total_cents          # references the column by name

-name: avg_order_value_cents
agg: average
expr: total_cents          # references the column by name
</code></pre>
<p><strong>Explanation:</strong> This is the one that would have bitten me. The semantic layer is a YAML config file, not SQL. It doesn't show up if you're just grepping through <code>.sql</code> files. But if you rename the column and forget to update these metric definitions, every dashboard using "total revenue" or "average order value" breaks silently.</p>
<hr />
<p><strong>Step 3: It traced the impact further downstream.</strong></p>
<p>Altimate Code didn't stop at the first layer. It followed the chain: if a breaking model feeds another model, that downstream model could be affected too.</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/27757262-64fd-4a02-941d-cf646a9095da.png" alt="" style="display:block;margin:0 auto" />

<p>Two mart tables sit downstream of <code>int_customer_lifetime</code>: <code>mart_customer_360</code> (full customer profiles, contains PII) and <code>mart_customer_cohorts</code> (customer segmentation). But neither one references <code>total_cents</code> directly. They use a derived column called <code>lifetime_revenue_cents</code>, which <code>int_customer_lifetime</code> produces from <code>total_cents</code> and then passes downstream under its own name.</p>
<p>Think of it like fixing a pipe in the basement. The faucets upstairs keep working as long as the pipe gets repaired properly. These two marts don't need code changes, they just need <code>int_customer_lifetime</code> to be fixed first.</p>
<p>One thing worth noting: <code>mart_customer_360</code> is tagged <code>compliance: 'CCPA / GDPR'</code> and <code>contains_pii: true</code>. It doesn't need code changes here, but in a governed environment, you still want to know that a compliance-tagged table sits in the blast radius.</p>
<hr />
<p><strong>Step 4: It presented the full blast radius report.</strong></p>
<p>Altimate Code assembled everything into a single view:</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/c12bdf06-d31e-4360-a6d7-cea47f7074fe.png" alt="" style="display:block;margin:0 auto" />

<table>
<thead>
<tr>
<th>#</th>
<th>File</th>
<th>What it is</th>
<th>Impact</th>
<th>Details</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td><code>stg_orders.sql</code></td>
<td>The model being changed</td>
<td>RENAME</td>
<td><code>total_cents</code> becomes <code>gross_revenue_cents</code></td>
</tr>
<tr>
<td>2</td>
<td><code>_staging.yml</code></td>
<td>Column documentation</td>
<td>RENAME</td>
<td>Update column name and description</td>
</tr>
<tr>
<td>3</td>
<td><code>int_order_enriched.sql</code></td>
<td>Order enrichment model</td>
<td>BREAKING</td>
<td>Directly references <code>orders.total_cents</code></td>
</tr>
<tr>
<td>4</td>
<td><code>int_customer_lifetime.sql</code></td>
<td>Customer lifetime value</td>
<td>BREAKING</td>
<td>Uses <code>sum(total_cents)</code> in a calculation</td>
</tr>
<tr>
<td>5</td>
<td><code>mart_return_analysis.sql</code></td>
<td>Return analysis report</td>
<td>SAFE</td>
<td>Uses <code>stg_orders</code> but never touches <code>total_cents</code></td>
</tr>
<tr>
<td>6</td>
<td><code>mart_customer_360.sql</code></td>
<td>Customer profile (PII)</td>
<td>CASCADING</td>
<td>Safe once <code>int_customer_lifetime</code> is fixed</td>
</tr>
<tr>
<td>7</td>
<td><code>mart_customer_cohorts.sql</code></td>
<td>Customer segmentation</td>
<td>CASCADING</td>
<td>Safe once <code>int_customer_lifetime</code> is fixed</td>
</tr>
<tr>
<td>8</td>
<td><code>sem_orders.yml</code></td>
<td>Business metric definitions</td>
<td>BREAKING</td>
<td>Two metrics reference <code>total_cents</code> by name</td>
</tr>
</tbody></table>
<p><strong>The bottom line: Five files need changes. Three are safe.</strong></p>
<p>Then the agent asked me:</p>
<blockquote>
<p><em>"I've identified 6 files that need changes across 3 layers (staging, intermediate, semantic). The 2 mart models downstream are safe because they reference derived column names. Shall I proceed with the rename?"</em></p>
</blockquote>
<img src="/blog/blast-radius-analysis-using-altimate-code/d24768f8-dcc5-40e0-abb6-d49f04bafbb8.png" alt="" style="display:block;margin:0 auto" />

<p>It didn't just run ahead. It stopped, showed me everything, and waited for the go-ahead.</p>
<hr />
<p><strong>Step 5: I approved. It applied all changes at once.</strong></p>
<p>After I said yes, Altimate Code updated all five files in a single pass. No partial updates, no window where half the models use the old name and half use the new one.</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/2ec8b3e5-3cfc-4194-95c2-3fcf8b27ac18.png" alt="" style="display:block;margin:0 auto" />

<p><code>stg_orders.sql</code> – aliased the source column:</p>
<pre><code class="language-sql">total_cents as gross_revenue_cents,  -- raw data keeps actual source column name, downstream sees new name
</code></pre>
<p>The raw data still has a column called <code>total_cents</code>. Instead of changing the source, the staging model gives it a new name. Everything downstream sees <code>gross_revenue_cents</code> from here on.</p>
<p><code>int_order_enriched.sql</code> – updated the reference:</p>
<pre><code class="language-sql">orders.gross_revenue_cents,  -- was: orders.total_cents
</code></pre>
<p><code>int_customer_lifetime.sql</code> – updated the aggregation:</p>
<pre><code class="language-sql">sum(gross_revenue_cents) as lifetime_revenue_cents,  -- was: sum(total_cents)
</code></pre>
<p><code>sem_orders.yml</code> – updated both metric definitions:</p>
<pre><code class="language-yaml">-name: total_revenue_cents
description:"Sum of gross revenue in cents (GAAP-aligned)"
expr: gross_revenue_cents   # was: total_cents

-name: avg_order_value_cents
description:"Average order value in cents (GAAP-aligned)"
expr: gross_revenue_cents   # was: total_cents
</code></pre>
<p><code>_staging.yml</code> – updated the documentation:</p>
<pre><code class="language-yaml">-name: gross_revenue_cents
description:"Gross revenue in cents, aligned with GAAP terminology"
</code></pre>
<hr />
<p><strong>Step 6: It built the entire project to confirm nothing broke.</strong></p>
<p>Altimate Code ran <code>altimate-dbt build</code> across all thirty-four models:</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/7a51f847-993b-4524-93d4-1e5ec034f8c4.png" alt="" style="display:block;margin:0 auto" />

<p>Thirty-six passed. Zero errors. Every staging view, intermediate table, and mart, including the PII-tagged <code>mart_customer_360</code>, built cleanly.</p>
<hr />
<p><strong>Step 7: It verified the column lineage end to end.</strong></p>
<p>As a final check, Altimate Code traced the data flow from source to destination to confirm the rename propagated correctly:</p>
<img src="/blog/blast-radius-analysis-using-altimate-code/3db3c89b-02a5-44ed-9c56-89f7ddd41f48.png" alt="" style="display:block;margin:0 auto" />

<p>The source column <code>TOTAL_CENTS</code> flows through the alias in staging, propagates correctly to both intermediate models, and the derived column names downstream (<code>lifetime_revenue_cents</code>) stay the same. Exactly what the blast radius report predicted.</p>
<hr />
<h2>Column Changes Are Never Just Column Changes</h2>
<p>A simple rename turned out to touch five files across three layers plus the semantic layer. Without the blast radius check, I would have updated <code>stg_orders</code>, run the build, and moved on. The semantic layer would have broken silently. Finance would have found out before I did.</p>
<hr />
<h2>How to read a blast radius report</h2>
<p>Every downstream asset gets one of four labels:</p>
<table>
<thead>
<tr>
<th>Label</th>
<th>What it means</th>
<th>What to do</th>
</tr>
</thead>
<tbody><tr>
<td><strong>BREAKING</strong></td>
<td>Directly uses the thing being changed. Will fail.</td>
<td>Update before or alongside the change</td>
</tr>
<tr>
<td><strong>CASCADING</strong></td>
<td>Depends on a breaking file, but doesn't use the changed column directly</td>
<td>Verify it works after the upstream fix. Usually no code changes.</td>
</tr>
<tr>
<td><strong>SAFE</strong></td>
<td>Depends on the changed model but never uses the specific column</td>
<td>Nothing</td>
</tr>
<tr>
<td><strong>UNKNOWN</strong></td>
<td>Can't determine impact (dynamic SQL, runtime-generated column names)</td>
<td>A human needs to look at it</td>
</tr>
</tbody></table>
<p>The report also flags compliance tags. In our case, <code>mart_customer_360</code> carries <code>compliance: 'CCPA / GDPR'</code> and <code>contains_pii: true</code>. It didn't need code changes here, but those flags make sure the right people know a compliance-tagged asset is in the blast radius.</p>
<hr />
<h2>Try it out yourself:</h2>
<p><strong>I ran this on a real project. To reproduce it:</strong></p>
<ol>
<li><p>Clone the CartWave demo project: <a href="https://github.com/altimateanas/ecommerce_demos.git">https://github.com/altimateanas/ecommerce_demos.git</a></p>
</li>
<li><p>Set up your database connection</p>
</li>
<li><p>Launch <a href="https://docs.altimate.sh/getting-started/">Altimate Code</a></p>
</li>
<li><p>Give Altimate Code the prompt "<em>Rename the column total_cents to gross_revenue_cents...</em>" from the article above</p>
</li>
</ol>
<p>It'll scan the project, map every dependency at the column level and show you a structured report before changing anything.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/blast-radius-analysis-using-altimate-code/872f1689-fd5d-494d-b1b9-cf001d92f029.png" type="image/png" />
  </item>
  <item>
    <title>We Created Data Engineering Skills for Claude Code</title>
    <link>https://altimate.ai/blog/we-created-data-engineering-skills-for-claude-code</link>
    <guid isPermaLink="true">https://altimate.ai/blog/we-created-data-engineering-skills-for-claude-code</guid>
    <pubDate>Mon, 11 May 2026 18:46:05 GMT</pubDate>
    <dc:creator>Steven Johnson</dc:creator>
    <description>Data engineering work spreads beyond SQL into lineage, tests, docs, cost, schema changes, and PII. We built skills that bring those workflows into Claude Code, covering dbt development, SQL review and</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/we-created-data-engineering-skills-for-claude-code/beb8fcfb-2ed1-4c46-ac6e-d7b964c96314.jpg" alt="We Created Data Engineering Skills for Claude Code" /></p>
<aside>
Data engineering work spreads beyond SQL into lineage, tests, docs, cost, schema changes, and PII. We built skills that bring those workflows into Claude Code, covering dbt development, SQL review and translation, data parity checks, schema migration safety, Snowflake cost analysis, PII auditing, and visualization.
</aside>

<p>Data engineering looks like software development from a distance, but the work has a different center of gravity. You still write code, review changes, and ship to production, but the real risk often lives outside the diff: downstream lineage, metric correctness, warehouse cost, schema drift, PII exposure, and whether the business can still trust the data after a change lands.</p>
<p>Most data engineering work also does not begin and end with writing SQL. A small model change can require checking upstream sources, understanding downstream impact, updating dbt docs, adding tests, comparing outputs, reviewing query performance, and making sure sensitive data is handled correctly. We created data engineering skills for Claude Code to bring those workflows into the coding agent experience, giving data teams reusable playbooks for the work they already do every day.</p>
<p>You can also access these skills through Altimate Code, our open-source LLM harness for data engineering, instead of installing each one individually in Claude Code. Altimate Code includes the skills out of the box and is ready to use with Claude:</p>
<pre><code class="language-bash">npm install -g altimate-code
</code></pre>
<p>The skills are open source, so you can use Altimate Code or browse the full set directly on GitHub: <a href="https://github.com/AltimateAI/altimate-code/tree/main/.opencode/skills">https://github.com/AltimateAI/altimate-code/tree/main/.opencode/skills</a></p>
<h2><strong>Skills as Data Engineering Playbooks</strong></h2>
<p>A skill is a reusable workflow Claude Code can load when a task calls for a specific kind of expertise. For data engineering, that means more than a prompt template. Each skill gives Claude Code guidance on what context to gather, what checks to run, what tools to use, what risks to watch for, and what kind of answer or artifact to produce.</p>
<p>For example, a SQL review skill should not only say whether a query is syntactically valid. It should look for anti-patterns, safety issues, readability problems, performance risks, and whether the query is appropriate for the warehouse or dialect. A dbt testing skill should understand model structure, schema YAML, unit test patterns, and the kinds of edge cases that usually cause production data issues.</p>
<p>The goal is to make Claude Code less dependent on one giant perfect prompt from the user. Instead of asking a data engineer to spell out every step, the skill carries the workflow: build the model, document the columns, add the tests, inspect the lineage, compare the outputs, review the SQL, and summarize what changed.</p>
<h2><strong>The Data Engineering Workflows We Covered</strong></h2>
<p>We organized the skills around the workflows data teams repeat every week: building models, reviewing SQL, validating changes, debugging warehouse issues, governing sensitive data, and communicating results. Each skill is focused on a specific job, but the real value comes from how they work together across the lifecycle of a data change.</p>
<p>The current skill set covers six areas:</p>
<ul>
<li><p>Building and maintaining dbt projects</p>
</li>
<li><p>Reviewing and improving SQL</p>
</li>
<li><p>Validating changes before they ship</p>
</li>
<li><p>Operating the warehouse</p>
</li>
<li><p>Governing data and team knowledge</p>
</li>
<li><p>Visualizing and explaining results</p>
</li>
</ul>
<hr />
<h2><strong>Building and Maintaining dbt Projects</strong></h2>
<p>The dbt skills cover the full lifecycle of a model: creating it, documenting it, testing it, understanding its downstream impact, and troubleshooting it when something breaks.</p>
<h4><strong>Creating and Changing Models</strong></h4>
<p>At it’s core, dbt is a tool that allows users to create SQL models, so we had to have a skill that creates dbt models. It is called <code>dbt-develop</code>.</p>
<p>This skill teaches Claude how to both write new dbt models and change existing ones. If you are a dbt user, you know that is not as simple as just writing SQL. You have to understand the project setup, dialect of the database, patterns across the staging, intermediate, and mart models, and the lineage of data flowing throughout the project.</p>
<h4>Documenting the Project</h4>
<p>If you are anything like me, you’ve spent days or even weeks creating an intricate dbt project that takes messy, raw data and forms it into beautiful marts that you deliver to your stakeholders. You neglect to create good documentation for your work because you created it so why would I need to write what it does?</p>
<p>A few weeks later you receive a message from a colleague asking what a specific column does, and you have no idea what the answer is. Documentation might have helped out a bit here.</p>
<p>When I say documentation, I mean going past the basic notes of <em>primary key</em> or <em>unique ID for customer.</em> Our skill, <code>dbt-docs</code>, writes documentation that will answer questions about models and columns that you might not have thought about.</p>
<p>The skill guides Claude to write about aggregations, primary and foreign keys, upstream tables, etc. Our hope is that this skill will allow you to stop answering questions about your models and columns and spend more time building more.</p>
<p><a href="https://youtu.be/PY63_Eu3Si4">https://youtu.be/PY63_Eu3Si4</a></p>
<h3><strong>Writing Tests for dbt Models</strong></h3>
<p>Before working in data, I was a teacher, so I have always loved a good test. Not the kind that exists just to make someone nervous, but the kind that makes expectations clear. A good test tells you what should happen, what matters, and where the gaps are.</p>
<p>That is exactly why tests matter in dbt. There is a special kind of confidence that comes from seeing a model run successfully. There is also a special kind of pain that comes from realizing later that the model ran successfully and still produced the wrong answer.</p>
<p>The <code>dbt-test</code> skill helps Claude Code add schema tests, unit tests, and data quality checks to dbt models. It can guide Claude Code through common checks like <code>not_null</code>, <code>unique</code>, <code>relationships</code>, and <code>accepted_values</code>, as well as custom generic or singular tests when a model needs something more specific.</p>
<p>For more complex model logic, the <code>dbt-unit-tests</code> skill goes deeper. It helps generate dbt unit tests by analyzing the model SQL, identifying upstream refs and sources, creating mock inputs, and assembling YAML that tests things like <code>CASE</code> statements, joins, window functions, null handling, aggregations, and incremental behavior.</p>
<p>The point is not to test for the sake of testing. It is to protect the assumptions your model depends on, so the next change does not quietly break the meaning of the data.</p>
<p><a href="https://youtu.be/O49qIMh2QPQ">https://youtu.be/O49qIMh2QPQ</a></p>
<h4><strong>Understanding and Fixing Impact</strong></h4>
<p>dbt changes have a habit of traveling. A small edit to a source model can ripple into downstream marts, dashboards, tests, and metric definitions. The <code>dbt-analyze</code> skill helps Claude Code reason about that blast radius before a change ships by inspecting dependency and lineage context, including column-level lineage where available.</p>
<p>The other side of impact is troubleshooting. When a dbt project fails to compile, a model errors at runtime, a test starts failing, or a dashboard suddenly looks wrong, the <code>dbt-troubleshoot</code> skill gives Claude Code a diagnostic workflow instead of leaving it to guess from the error message alone. It helps separate compilation issues, warehouse errors, test failures, incorrect data, and performance problems.</p>
<p>Together, these skills help Claude Code answer two questions that come up constantly in dbt work: “What could this change affect?” and “What is actually going wrong?”</p>
<hr />
<h2><strong>Reviewing and Improving SQL</strong></h2>
<p>Even in a dbt-heavy world, SQL is still the language data teams use to express business logic. But good SQL is not just SQL that runs. It should be readable, safe, efficient, and appropriate for the warehouse it runs on. The SQL skills help Claude Code review, optimize, and translate queries across the systems data teams actually use.</p>
<h4><strong>Reviewing SQL Before It Ships</strong></h4>
<p>Every data team has seen a query that technically works but makes you nervous. Maybe it has a risky join, a missing filter, unclear business logic, a performance issue hiding in plain sight, or a pattern that will be painful for the next person to maintain.</p>
<p>The <code>sql-review</code> skill gives Claude Code a pre-merge review workflow for SQL. It guides Claude Code to look for syntax issues, anti-patterns, readability problems, performance risks, and safety concerns before the query lands in production.</p>
<p>The goal is not just to ask, “Does this query run?” It is to ask, “Is this query understandable, reliable, and safe enough for the data system it is about to become part of?”</p>
<h4><strong>Optimizing Slow or Expensive Queries</strong></h4>
<p>Slow queries are rarely just an inconvenience in data engineering. They can block development, delay dashboards, frustrate stakeholders, and quietly drive up warehouse costs. A query that was fine on a small table can become a problem as data volume grows or as more teams start depending on it.</p>
<p>The <code>query-optimize</code> skill helps Claude Code inspect SQL with performance in mind. It can look for inefficient joins, unnecessary scans, filtering issues, aggregation patterns, and opportunities to rewrite the query in a way that is easier for the warehouse to execute.</p>
<p>This is where Claude Code becomes useful beyond code generation. It can help reason through why a query is slow, what tradeoffs are available, and how to make the SQL more efficient without losing the business logic that made the query valuable in the first place.</p>
<h4><strong>Translating Across Dialects</strong></h4>
<p>If you’ve done much traveling, you know that speaking the same language does not always mean speaking it the same way. SQL is similar. Snowflake, BigQuery, Databricks, Postgres, Redshift, MySQL, SQL Server, and DuckDB all share the same broad language, but each warehouse has its own syntax, functions, conventions, and sharp edges.</p>
<p>A query written for BigQuery will not always translate cleanly into Snowflake. The same is true when moving models between warehouses, supporting multiple customer environments, or trying to standardize logic across a mixed data stack.</p>
<p>That is why we built the <code>sql-translate</code> skill. It helps Claude Code translate SQL from one dialect to another while preserving the intent of the query. Think of it as Duolingo for Claude Code, except instead of asking it to practice ordering coffee, you are asking it to keep your business logic intact across warehouses.</p>
<p>If your team is migrating warehouses or working across multiple SQL engines, this skill gives Claude Code a much better starting point for making those translations safely.</p>
<hr />
<h2><strong>Validating Changes Before They Ship</strong></h2>
<p>In software engineering, tests often tell you whether a change broke expected behavior. In data engineering, validation can be harder to pin down. A model can run, a query can return rows, and a migration can apply successfully while the meaning of the data has still changed.</p>
<p>That is why this category matters so much. Data teams do not just need help making changes. They need help understanding whether those changes are safe to ship. The validation skills help Claude Code compare outputs, inspect lineage, and look for migration risks before a change reaches production.</p>
<h3><strong>Comparing Data Outputs</strong></h3>
<p>One of the most common questions in data work is also one of the most important: did this change alter the data?</p>
<p>Sometimes the answer should be yes. You fixed a bug, changed a business definition, or added new logic. But often, especially during a refactor or migration, the goal is to preserve behavior while changing the implementation. That is where the <code>data-parity</code> skill becomes useful.</p>
<p>The <code>data-parity</code> skill helps Claude Code compare two tables or query results and diagnose exactly how they differ. It can be used for migration validation, ETL regression checks, and query refactor verification. Instead of stopping at “these counts do not match,” the workflow pushes toward understanding where they differ, why they differ, and whether the difference is expected.</p>
<p>Think of it as asking Claude Code to check the receipt before you leave the store. The change may look fine at a glance, but you want to know whether the numbers actually add up.</p>
<h3><strong>Seeing How Lineage Changed</strong></h3>
<p>A data change is not only about the rows that come out the other side. It is also about how values move through the system. When the lineage changes, the meaning of a column can change with it.</p>
<p>The <code>lineage-diff</code> skill helps Claude Code compare column-level lineage between two versions of a SQL query or model. It can show which data flow edges were added, removed, or changed, giving the reviewer a clearer picture of how the transformation shifted.</p>
<p>This is especially useful when reviewing changes that look small in the SQL but may affect important downstream fields. A join changes. A source column is swapped. A derived field starts pulling from a different upstream path. The query may still run, but the story of the data has changed.</p>
<p>The goal is to make those invisible changes visible before they surprise someone downstream.</p>
<h3><strong>Catching Migration Risk</strong></h3>
<p>Schema changes are another place where “it ran successfully” is not enough. A migration can apply cleanly and still introduce data loss, break assumptions, or create problems for downstream consumers.</p>
<p>The <code>schema-migration</code> skill helps Claude Code analyze DDL changes before they are applied. It looks for risks like type narrowing, dropped columns, missing defaults, removed constraints, and other breaking column changes that can quietly turn into production issues.</p>
<p>This matters because schema migrations often feel mechanical until they are not. Renaming a column, changing a type, or tightening a constraint might look straightforward in code, but those changes can affect ingestion jobs, BI tools, reverse ETL flows, contracts, and every team that has built something on top of the data.</p>
<p>The skill gives Claude Code a migration review mindset: not just “Can this statement execute?” but “What could this break if it does?”</p>
<hr />
<h2><strong>Operating the Warehouse</strong></h2>
<p>Once data work is running in production, a different set of questions starts to matter. What is expensive? What is slow? What changed? Which workloads are driving spend? Which queries or models need attention? The warehouse is not just where data lives. It is also where performance and cost decisions show up.</p>
<p>The warehouse operations skills help Claude Code reason about those questions as part of the engineering workflow. Instead of treating cost and performance as separate admin tasks, these skills bring them closer to the code, queries, and models that created them.</p>
<h3><strong>Understanding Cost</strong></h3>
<p>Warehouse spend can be difficult to reason about because the cost is usually spread across queries, users, jobs, warehouses, and workloads. A dashboard may feel slow, a bill may jump, or a team may notice that a routine transformation suddenly got more expensive, but finding the cause is not always obvious.</p>
<p>The <code>cost-report</code> skill helps Claude Code analyze Snowflake query costs and identify optimization opportunities. It can help look at expensive queries, warehouse usage, credit consumption, unused resources, and patterns that may point to waste or inefficient workloads.</p>
<p>This gives Claude Code a FinOps lens. Not in the “please enjoy this spreadsheet of guilt” sense, but in the useful sense: where is the money going, what changed, and what can we do about it?</p>
<h3><strong>Diagnosing Operational Issues</strong></h3>
<p>Cost is only one part of operating a warehouse. Data teams also have to deal with slow queries, failing jobs, runtime errors, and models that behave differently as volume grows.</p>
<p>This is where several skills work together. The <code>query-optimize</code> skill helps Claude Code reason about slow or inefficient SQL. The <code>dbt-troubleshoot</code> skill gives it a workflow for compilation failures, runtime database errors, failing tests, incorrect data, and performance issues in dbt projects.</p>
<p>The goal is to make Claude Code useful when something is not healthy in production. It can help move from symptoms to causes: from “this dashboard is slow,” “this model failed,” or “our warehouse spend jumped” toward a clearer explanation of what is happening and what to try next.</p>
<hr />
<h2><strong>Governance, Privacy, and Team Knowledge</strong></h2>
<p>Data engineering also carries responsibilities that do not fit neatly into “write the model” or “make the query faster.” Teams need to know where sensitive data lives, whether a query exposes it, and whether new work follows the standards the team has already agreed on. The governance and training skills help Claude Code operate with more awareness of privacy, compliance, and team-specific conventions.</p>
<h3><strong>Auditing Sensitive Data</strong></h3>
<p>Sensitive data has a way of showing up where you least expect it. An email field gets added to a downstream model. A phone number moves into an analytics table. An IP address appears in a query result that was supposed to be safe to share. Unlike pie, PII is much better when it is not casually passed around.</p>
<p>The <code>pii-audit</code> skill helps Claude Code classify schema columns for personally identifiable information and sensitive data, including direct identifiers like SSNs, emails, phone numbers, names, addresses, and credit card numbers, as well as quasi-identifiers like dates of birth, zip codes, IP addresses, and device IDs.</p>
<p>It can also check whether a query or dbt model exposes PII, distinguish between sensitive fields used internally and sensitive fields returned in the output, and help generate a PII inventory for compliance workflows like GDPR, CCPA, and HIPAA.</p>
<p>The point is not to turn Claude Code into a compliance department. It is to give it enough privacy awareness to pause at the right moments, surface risk, and help data teams avoid accidentally spreading sensitive data through models, reports, or ad hoc queries.</p>
<p><a href="https://youtu.be/KtWwjVIhlGI">https://youtu.be/KtWwjVIhlGI</a></p>
<h3><strong>Teaching Claude Code Your Team’s Standards</strong></h3>
<p>That same teaching instinct shows up in the <code>teach</code>, <code>train</code>, and <code>training-status</code> skills. A lot of what makes someone effective on a data team is not just knowing SQL or dbt. It is learning the patterns, preferences, definitions, and little bits of context that make work fit the team around it.</p>
<p>Every data team has conventions that are obvious to the people who have been there long enough and invisible to everyone else. How staging models should be named. What belongs in marts. Which patterns are encouraged. Which shortcuts should be avoided. Which business definitions have sharp edges. Most of that knowledge lives in scattered docs, review comments, Slack threads, and the brains of the people who have answered the same question ten times.</p>
<p>The <code>teach</code> skill lets you show Claude Code an example file from your codebase and extract reusable patterns from it. The <code>train</code> skill helps Claude Code learn team standards from a document, style guide, or review checklist. The <code>training-status</code> skill shows what it has learned so far.</p>
<p>These skills help Claude Code move closer to the way your team actually works. The goal is not just technically valid output. It is output that reflects your standards, your naming conventions, your modeling patterns, and the context your team has built over time.</p>
<hr />
<h3><strong>Visualizing and Explaining Results</strong></h3>
<p>Data work does not end when the query returns rows. At some point, someone needs to understand what the data is saying. That might mean a chart for a trend, a dashboard for a team, a KPI view for leadership, or a more interactive way to explore a dataset.</p>
<p>The <code>data-viz</code> skill helps Claude Code turn data into visual interfaces: charts, dashboards, KPI cards, analytics views, and reporting experiences. It guides Claude Code toward modern component libraries like Recharts, Tremor, Nivo, D3, Victory, visx, and shadcn/ui, depending on the project.</p>
<p>This matters because the last mile of data work is often communication. A model can be correct, tested, documented, and optimized, but if people cannot understand the result, the work is not finished. The <code>data-viz</code> skill helps Claude Code move from “here is the data” to “here is what the data means.”</p>
<hr />
<p>Claude Code is already a powerful place to work with code. These skills make it more useful for the specific work data teams do every day: building models, writing tests, reviewing SQL, validating changes, checking lineage, auditing PII, understanding cost, translating dialects, and explaining results.</p>
<p>The goal is not to replace data engineers. It is to give them a better teammate inside the workflows they already know. Data engineering requires code, context, caution, and communication. These skills give Claude Code more of that context, so it can help with the work around the code, not just the code itself.</p>
<p>If you want to use the skills without installing them one by one in Claude Code, they are included in Altimate Code, our open-source LLM harness for data engineering. Altimate Code comes with these skills installed and is ready to work with Claude:</p>
<pre><code class="language-bash">npm install -g altimate-code
</code></pre>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/we-created-data-engineering-skills-for-claude-code/beb8fcfb-2ed1-4c46-ac6e-d7b964c96314.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>Best Data Conferences 2026: The Complete Guide</title>
    <link>https://altimate.ai/blog/best-data-conferences-2026-the-complete-guide</link>
    <guid isPermaLink="true">https://altimate.ai/blog/best-data-conferences-2026-the-complete-guide</guid>
    <pubDate>Mon, 11 May 2026 18:31:11 GMT</pubDate>
    <dc:creator>Steven Johnson</dc:creator>
    <description>If you&apos;re trying to figure out which remaining data conferences in 2026 are worth your time and travel budget, this is the list. We&apos;ve covered the biggest events on the calendar, from global platform</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/best-data-conferences-2026-the-complete-guide/ee92f384-3c6f-4d0c-90a0-79f0018e6387.png" alt="Best Data Conferences 2026: The Complete Guide" /></p>
<hr />
<p>If you're trying to figure out which remaining data conferences in 2026 are worth your time and travel budget, this is the list. We've covered the biggest events on the calendar, from global platform summits drawing 20,000+ attendees to practitioner-focused gatherings where the real technical conversations happen.</p>
<p>Listed in chronological order.</p>
<hr />
<h2><a href="https://www.gartner.com/en/conferences/na/data-analytics-us">Gartner Data &amp; Analytics Summit</a></h2>
<p><strong>March 9-11 | Gaylord Palms, Orlando, FL | ~5,000 attendees</strong></p>
<p>If your job involves data strategy, AI governance, or making the case to leadership for data investments, this one belongs near the top of your list. The summit runs on research from Gartner analysts: over 60 experts delivering 137 sessions across five main tracks and three spotlight tracks. This year's focus was squarely on moving past AI pilots and into production-grade AI that actually delivers ROI.</p>
<p>The crowd skews toward senior roles: CDAOs, heads of AI, data architecture leads, data management executives. The format matches that audience: keynotes and roundtables built for strategic conversation, not product demos. There are 130+ vendors in the Exhibit Showcase if that's useful, but the sessions are where the value is. Gartner also runs this summit in London and Sydney for teams outside North America.</p>
<hr />
<h2><a href="https://www.salesforce.com/tableau-conference/">Tableau Conference</a></h2>
<p><strong>May 5-7 | San Diego Convention Center, San Diego, CA | ~8,000 attendees</strong></p>
<p><strong>TC26</strong> is three days of 300+ expert-led sessions, 150+ hands-on trainings, and the kind of community programming that makes this feel less like a tech conference and more like a reunion. Tableau's community calls itself the DataFam for a reason. The culture is genuinely welcoming in a way that most data conferences aren't.</p>
<p>Content this year centers on agentic analytics, interoperability, and new product integrations. If your team uses Tableau day-to-day, the skill-building alone makes this worth attending. Sessions run from beginner dashboard design to advanced AI integration. There's also Iron Viz (a live data viz competition), Tableau Doctor for 1:1 expert help, and Salesforce+ livestreams for anyone who can't make it in person.</p>
<hr />
<h2><a href="https://www.snowflake.com/en/summit/">Snowflake Summit</a></h2>
<p><strong>June 1-4 | Moscone Center, San Francisco, CA | ~20,000 attendees</strong></p>
<p><strong>Snowflake Summit 2026</strong> has 500+ sessions, hands-on labs, training and certification, and an expo floor with 190+ partner booths. The Builders Hub is specifically for developers: bootcamp sessions and live demos. The Industry Zone covers vertical-specific content for finance, healthcare, retail, and more.</p>
<p>The theme this year is agentic intelligence: how to move from isolated data strategies to connected, AI-powered enterprise experiences. If your team runs on Snowflake, this is where you get ahead on what's coming from the platform and hear real implementation stories from companies that have already shipped it. Main keynotes are livestreamed free for non-registrants.</p>
<p>Catch the Altimate AI team at booth 1311</p>
<hr />
<h2><a href="https://www.databricks.com/dataaisummit">Databricks Data + AI Summit</a></h2>
<p><strong>June 15-18 | Moscone Center, San Francisco, CA | ~22,000 attendees</strong></p>
<p><strong>Data + AI Summit</strong> brings together data engineers, scientists, architects, ML engineers, and executives from over 160 countries across 800+ sessions covering data engineering, warehousing, governance, analytics, agentic AI, and AI/BI.</p>
<p>If you're working with Apache Spark, Delta Lake, Apache Iceberg, MLflow, or dbt alongside Databricks, this is where roadmaps get announced and where you'll find the most advanced technical content on those tools. The conference also offers new certification courses on-site. One caveat: it's a big event. Plan your session schedule before you arrive or you'll spend the week just trying to navigate the venue.</p>
<p>Catch the Altimate AI team at booth 577</p>
<hr />
<h2><a href="https://ai4.io/vegas/">Ai4</a></h2>
<p><strong>August 4-6 | Las Vegas, NV | ~12,000 attendees</strong></p>
<p>America's largest independent AI conference, drawing 12,000+ executives and decision-makers from 90+ countries. Ai4 is enterprise-focused. The emphasis is on real-world AI implementation and measurable business outcomes, not research. Tracks are organized by industry (finance, healthcare, retail, manufacturing) and by function (AI strategy, generative AI, AI agents, automation).</p>
<p>The audience skews toward business and technical leadership. If you're evaluating AI strategy or want to see how peers in adjacent industries are actually deploying AI in production, this is a useful venue. For teams wondering whether their AI initiatives are in line with what the broader market is doing, the comparison is genuinely worth making.</p>
<hr />
<h2><a href="https://coalesce.getdbt.com/">dbt Summit</a> <em>(formerly Coalesce)</em></h2>
<p><strong>September 15-18 | The Cosmopolitan, Las Vegas, NV | ~3,000 attendees</strong></p>
<p>Coalesce has a new name. <strong>dbt Summit 2026</strong> is the world's largest gathering of dbt users: analytics engineers, data engineers, data architects, and the data leaders working alongside them. The rebrand reflects how the event has grown from a community conference into a full industry summit, spanning four days with 100+ sessions across keynotes, breakout tracks, and hands-on labs.</p>
<p>The conversations here are practitioner-driven. You won't find a lot of polished vendor pitches. You'll find engineers being honest about what's working and what isn't. Key themes include dbt Mesh, data contracts, AI-ready data architectures, incremental models, and how analytics engineering intersects with ML workflows. For data teams building on dbt, this is the one worth planning around.</p>
<p>Catch the Altimate AI team on the Expo floor</p>
<hr />
<h2><a href="https://www.bigdataldn.com/en-gb.html">Big Data LDN</a></h2>
<p><strong>September 23-24 | Olympia London, London, England | Free to attend</strong></p>
<p>The UK's largest data, analytics, and AI event and the most important data conference on the European calendar. Big Data LDN brings together engineers, architects, data leaders, and practitioners for two days of 400+ seminars across 15 free-to-attend conference theatres. Speakers come from Google, AWS, TikTok, Spotify, Snowflake, Databricks, and a wide range of startups.</p>
<p>Free registration, 130+ exhibitors ranging from major platform vendors to early-stage companies, and sessions covering AI governance, data engineering, and data products. In 2026, a co-located event called Data Driven LDN runs on September 22nd, focused specifically on AI agents, AI governance, and data products for senior practitioners who want deeper dives.</p>
<p>Catch the Altimate AI team on the Expo floor</p>
<hr />
<h2>How to Pick the Right Data Conference in 2026</h2>
<p>Nobody can do all of these, so a few filters are worth applying. If your team runs on Snowflake, Snowflake Summit is the obvious call. The same logic applies for dbt and dbt Summit. Platform-specific conferences tend to have the highest signal-to-noise for teams already using those tools. Data leaders and strategists get the most out of Gartner and Ai4. Practitioners and engineers tend to get more hands-on value from dbt Summit and the Databricks summit. Tableau Conference is its own category: best for teams where Tableau is the primary visualization layer. European teams should have Big Data LDN near the top of the list. It's free, comprehensive, and the audience quality is high.</p>
<p>Pick the ones where your stack, your role, and your team's current problems overlap with the program. That overlap is usually obvious once you look.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/best-data-conferences-2026-the-complete-guide/ee92f384-3c6f-4d0c-90a0-79f0018e6387.png" type="image/png" />
  </item>
  <item>
    <title>Claude Code or Altimate Code for Data Engineering?</title>
    <link>https://altimate.ai/blog/claude-code-or-altimate-code-for-data-engineering</link>
    <guid isPermaLink="true">https://altimate.ai/blog/claude-code-or-altimate-code-for-data-engineering</guid>
    <pubDate>Thu, 23 Apr 2026 17:00:26 GMT</pubDate>
    <dc:creator>Muhammad Anas Farooqui</dc:creator>
    <category>claude-code</category>
    <category>altimate-code</category>
    <category>altimateAI</category>
    <description>Claude Code is fast, writes good software code, and can even handle dbt models and other data engineering tasks to certain extent.
At first glance Altimate Code, the data engineering harness, may seem</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/claude-code-or-altimate-code-for-data-engineering/a5d2ee61-e0d3-4b90-9909-376d54ed2949.jpg" alt="Claude Code or Altimate Code for Data Engineering?" /></p>
<p>Claude Code is fast, writes good software code, and can even handle dbt models and other data engineering tasks to certain extent.</p>
<p>At first glance <a href="https://docs.altimate.sh/getting-started/">Altimate Code</a>, the data engineering harness, may seem to do similar things. So, do we need both? Is one a replacement for the other?</p>
<p>We ran an experiment to find out. We used the same prompt, the same model (Claude Opus 4.6), and the same codebase. One run with Claude Code alone, one run with Altimate Code. The results were not close.</p>
<hr />
<h2>What Claude Code Actually Is</h2>
<p>Claude Code is a general-purpose agentic coding tool that reads files, runs shell commands, edits code etc. For data engineering, it draws on Claude's extensive training coverage of SQL dialects and dbt conventions.</p>
<p>But Claude Code is no data engineering expert. It has no deterministic SQL anti-pattern engine, no static lineage tracer, no PII classifier, no schema diff tool that programmatically flags breaking changes.</p>
<p>And there is no evidence the team at Anthropic is focused on making it any better at these tasks.</p>
<h2>What Altimate Code Actually Is</h2>
<p><a href="https://docs.altimate.sh/getting-started/">Altimate Code</a> is an open-source data engineering harness with 100+ specialized tools for building, validating, optimizing, and shipping data products. It uses LLMs (Claude, GPT, Gemini, or any of 17+ providers) as its AI backend, but routes every task through domain-specific tooling that general-purpose agents do not have:</p>
<ul>
<li><p><strong>Live warehouse connection</strong> -- connects directly to various warehouses with auto-discovery from profiles.yml or environment variables.</p>
</li>
<li><p><strong>dbt-native build and test</strong> -- runs real <code>dbt build</code> against your warehouse, materializing tables and executing every data test.</p>
</li>
<li><p><strong>Column-level lineage</strong> -- traces every column from source through joins, CTEs, and subqueries to final output in real time.</p>
</li>
<li><p><strong>PII detection</strong> -- scans schemas across 15+ PII categories (SSN, email, phone, DOB, health data) with confidence scores.</p>
</li>
<li><p><strong>Impact analysis and schema diff</strong> -- calculates blast radius across your full dbt DAG and produces column-level before/after diffs with breaking change classification.</p>
</li>
<li><p><strong>SQL quality grading</strong> -- scores SQL on syntax, style, safety, and complexity (A-F) for objective, reproducible code review.</p>
</li>
<li><p><strong>Enforced agent modes</strong> -- Builder (can modify), Analyst (read-only), Plan (design only) -- enforced at the harness level, not by prompt. You cannot DROP TABLE in Analyst mode regardless of what the LLM suggests.</p>
</li>
<li><p><strong>Project conventions via AGENTS.md</strong> -- team-wide rules loaded into every session's system prompt for consistency across engineers and CI.</p>
</li>
</ul>
<h2>How Claude Code and Altimate Code Work Together</h2>
<p>Claude Code and Altimate Code are not competitors or alternatives .They occupy different layers of the stack. Claude Code is a general-purpose coding agent. Altimate Code is a domain-specific data engineering harness.</p>
<p>When used together, Claude Code handles task orchestration and conversational context while Altimate Code’s tools handle warehouse connectivity, lineage tracing, PII scanning, build execution, and impact analysis. The LLM’s reasoning improves when it has access to specialized tools enabling access to real data, real schemas, and real test results instead of guessing from file contents alone.</p>
<p>The comparison in this post demonstrates why domain-specific tooling matters for data engineering work.</p>
<hr />
<h2>The Experiment: Claude Code vs. Altimate Code</h2>
<p>As an experiment we took a realistic, broken dbt model <code>mart_patient_360</code> from a demo dbt healthcare project <code>medflow-analytics</code> — a scenario that data engineering teams encounter regularly — and gave the exact same prompt to two setups:</p>
<ol>
<li><p>Claude Code standalone and</p>
</li>
<li><p>Altimate Code + Claude Code, same codebase, and same task.</p>
</li>
</ol>
<p><strong>The goal:</strong> to see whether domain-specific data engineering tooling produces meaningfully different outcomes than a general-purpose coding agent when the task involves schema accuracy, HIPAA compliance, build verification, and downstream impact analysis — the things that actually matter in production data work.</p>
<p><strong>Model:</strong> Claude Opus 4.6 was used in both experiments to ensure a fair comparison.</p>
<p><strong>The prompt we used :</strong></p>
<blockquote>
<p><em>The</em> <code>mart_patient_360</code> <em>model is incomplete. Right now it joins patients, encounters, diagnoses, medications, and lab_results but the SELECT is mostly empty — it’s missing the</em> <code>patient_id</code> <em>primary key, has no aggregated metrics, and just exposes raw PII fields like SSN and phone number. I need you to build this out into a proper patient 360 view: add the</em> <code>patient_id</code> <em>key, total encounter count, unique diagnosis count, active medication count, most recent lab result date, days since last visit, and a patient risk tier (high/medium/low based on encounter frequency and diagnosis count). The model is tagged as PII/HIPAA-restricted. Make sure the final model is safe to materialize, fix any compliance issues you see, and tell me what downstream impacts or governance concerns I should be aware of before merging.</em></p>
</blockquote>
<p><strong>Claude Code:</strong></p>
<img src="/blog/claude-code-or-altimate-code-for-data-engineering/c14f12cd-3144-4f50-8c58-2b253ebe2912.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Altimate Code:</strong></p>
<img src="/blog/claude-code-or-altimate-code-for-data-engineering/c24e57ea-bb2b-48fc-9956-ec2d59b25a8d.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Head-to-Head Results: Data Engineering Harness Vs. General Purpose Coding Assistant</h2>
<h3>Claude Code Output:</h3>
<p>Enhanced the model but without execution or proper validation, surfaced limited insights:</p>
<img src="/blog/claude-code-or-altimate-code-for-data-engineering/1841f898-c013-48f3-9912-4b67935202f6.png" alt="Screenshot of the Claude Code output" style="display:block;margin:0 auto" />

<h3>Altimate Code Output:</h3>
<p>Unlike Claude Code, Altimate Code enhanced the dbt model, executed it, did proper validation, and surfaced detailed insights:</p>
<img src="/blog/claude-code-or-altimate-code-for-data-engineering/2335e045-23d6-44d7-8703-6e51fafc7b31.png" alt="Screenshot of the Altimate Code output" style="display:block;margin:0 auto" />

<h2>Detailed Findings</h2>
<h3>1. PII and HIPAA Compliance</h3>
<p>This is where the gap was most visible and most consequential.</p>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>Claude Code (Opus 4.6)</th>
<th>Altimate Code (Opus 4.6)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>SSN handling</strong></td>
<td>Hashed with <code>sha2(ssn, 256)</code> — SSN still flows through the query pipeline.</td>
<td>Removed entirely — SSN is never selected into any CTE. It never touches the query.</td>
</tr>
<tr>
<td><strong>full_name, phone, email, address</strong></td>
<td>Kept in the final model output. Still materialized to Snowflake disk.</td>
<td>Dropped completely from the model with explicit per-column rationale.</td>
</tr>
<tr>
<td><strong>PII verification</strong></td>
<td>None — assumed the code changes were sufficient.</td>
<td>Ran automated <code>altimate_core_classify_pii</code> scan on the output schema. Caught that <code>full_name</code> was still flowing through a CTE even though it wasn’t in the final SELECT. Removed it in a second pass.</td>
</tr>
<tr>
<td><strong>Philosophy</strong></td>
<td>“Mask the PII.” Sensitive data still exists in the table, just obfuscated.</td>
<td>“Eliminate the PII.” The mart never touches it. Consumers who need PII use RBAC on the staging layer.</td>
</tr>
</tbody></table>
<p><strong>Why this matters:</strong> Claude Code’s SHA-256 hash of SSN is a common pattern, but it’s a weaker approach than most teams realize. SSNs are 9 digits — roughly 900 million possible values. Altimate Code’s approach of full elimination is the correct HIPAA-compliant pattern for analytical marts.</p>
<p>In our experiment, Altimate Code’s <code>lineage_check</code> tool revealed that <code>full_name</code> (a PII field) was flowing through a CTE even though it wasn’t in the final SELECT. Claude Code missed this entirely. Altimate Code’s lineage engine claims 100% edge match accuracy across 500 benchmark queries.</p>
<h3>2. Schema Accuracy: Did It Actually Build?</h3>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>Claude Code (Opus 4.6)</th>
<th>Altimate Code (Opus 4.6)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Columns referenced</strong></td>
<td>Used <code>gender</code>, <code>race</code>, <code>ethnicity</code>, <code>primary_care_provider_id</code> from <code>stg_patients</code> (none of these exist in the actual SQL) plus <code>blood_type</code> (which exists in SQL but isn’t in the YAML). Also grouped <code>stg_diagnoses</code> and <code>stg_medications</code> by <code>patient_id</code> directly.</td>
<td>Only used columns confirmed to exist in the actual staging SQL.</td>
</tr>
<tr>
<td><strong>The problem</strong></td>
<td>The four phantom columns are documented in <code>_staging.yml</code> but <strong>not selected</strong> in <code>stg_patients.sql</code>. The actual SQL only selects: <code>patient_id, full_name, ssn, date_of_birth, phone, email, address, blood_type, insurance_id, created_at</code>. Additionally, <code>stg_diagnoses</code> and <code>stg_medications</code> do not contain <code>patient_id</code> — Claude Code assumed they did.</td>
<td>Cross-referenced the YAML documentation against the actual SQL files AND the seed CSV headers to identify exact available columns.</td>
</tr>
<tr>
<td><strong>Diagnosis join</strong></td>
<td>Grouped <code>stg_diagnoses</code> by <code>patient_id</code> directly.</td>
<td>Joined <code>stg_diagnoses</code> to <code>stg_encounters</code> via <code>encounter_id</code> to get <code>patient_id</code>, then grouped. Same pattern applied for <code>stg_medications.</code></td>
</tr>
<tr>
<td><strong>Would it build?</strong></td>
<td><strong>No:</strong> would fail on at least six missing column references (4 phantom from <code>stg_patients</code>, plus <code>patient_id</code> in both <code>stg_diagnoses</code> and <code>stg_medications</code>).</td>
<td><strong>Yes:</strong> <strong>PASS=40, WARN=0, ERROR=0</strong> across the full project.</td>
</tr>
</tbody></table>
<p><strong>Why this matters:</strong> Claude Code trusted the YAML documentation, which was out of sync with the actual SQL in multiple directions. Some columns were documented but missing from the SQL, while <code>blood_type</code> was the reverse case (in the SQL but undocumented). This is extremely common in real dbt projects. Altimate Code verified against multiple sources (SQL, YAML, seed data) and resolved the discrepancies.</p>
<p>The <code>altimate_core_schema_diff</code> tool produces a column-level before/after comparison with explicit breaking change classification (e.g. <code>[BREAKING] Column 'ssn' removed</code>). In our experiment, this confirmed 16 schema changes with 6 breaking giving the team an exact migration checklist.</p>
<h3>3. Build Verification and Data Validation</h3>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>Claude Code (Opus 4.6)</th>
<th>Altimate Code (Opus 4.6)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>dbt build attempted</strong></td>
<td>No</td>
<td>Yes: <code>altimate-dbt build --model mart_patient_360.</code></td>
</tr>
<tr>
<td><strong>Tests run</strong></td>
<td>Never executed</td>
<td>8 data tests, all passing (unique, not_null, accepted_values).</td>
</tr>
<tr>
<td><strong>Full project build</strong></td>
<td>Never attempted</td>
<td><strong>PASS=40, WARN=0, ERROR=0</strong> — 20 models, 10 seeds, 8 tests, 2 project hooks.</td>
</tr>
<tr>
<td><strong>Data validation</strong></td>
<td>None</td>
<td>Queried Snowflake directly: confirmed 1,000 patients, verified risk distribution (719 low, 278 medium, 3 high), spot-checked high-risk and low-risk patients.</td>
</tr>
<tr>
<td><strong>SQL quality checks</strong></td>
<td>None</td>
<td>Ran <code>sql_analyze</code>, <code>altimate_core_check</code>, and <code>altimate_core_grade.</code></td>
</tr>
</tbody></table>
<p><strong>Why this matters:</strong> Claude Code wrote the code and declared it done. Altimate Code wrote the code, built it on Snowflake, ran every test, queried the output data, and verified the results made clinical sense. In production data engineering, “the SQL looks right” is not the same as “it works.”</p>
<h3>4. Downstream Impact Analysis</h3>
<table>
<thead>
<tr>
<th>Aspect</th>
<th>Claude Code (Opus 4.6)</th>
<th>Altimate Code (Opus 4.6)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Blast radius assessment</strong></td>
<td>Manually identified <code>vw_patient_summary_deidentified</code> as downstream and updated it</td>
<td>Ran automated <code>impact_analysis</code> — confirmed 0/20 downstream dbt models affected.</td>
</tr>
<tr>
<td><strong>Schema diff</strong></td>
<td>Described breaking changes in a text table.</td>
<td>Ran <code>altimate_core_schema_diff</code> — automated analysis: <strong>16 changes, 6 breaking</strong>, with exact column-level detail.</td>
</tr>
<tr>
<td><strong>Breaking change detail</strong></td>
<td>Listed columns removed.</td>
<td>Categorized each: <code>[BREAKING] Column 'mart_patient_360.ssn' removed</code>, <code>[info] Column 'mart_patient_360.patient_risk_tier' added (VARCHAR).</code></td>
</tr>
<tr>
<td><strong>External consumer warnings</strong></td>
<td>Generic: “verify that Snowflake row-access policies are correctly scoped”.</td>
<td>Specific: BI tools, RBAC enforcement, CI check suggestion for <code>restricted</code> tag containment, non-determinism warning for <code>current_date</code> usage.</td>
</tr>
</tbody></table>
<p><strong>Why this matters:</strong> In production data environments, the most dangerous changes are the ones that look safe in isolation. Altimate Code's impact_analysis tool traverses the full DAG programmatically, and its schema_diff produces a migration checklist that a team lead can review.</p>
<h3>5. Governance Recommendations</h3>
<table>
<thead>
<tr>
<th>Topic</th>
<th>Claude Code (Opus 4.6)</th>
<th>Altimate Code (Opus 4.6)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>date_of_birth</strong></td>
<td>Mentioned Safe Harbor in passing</td>
<td>Specific recommendation: “consider age-banding for de-identified datasets per HIPAA Safe Harbor” — included in YAML column description.</td>
</tr>
<tr>
<td><strong>Non-determinism</strong></td>
<td>Not mentioned</td>
<td>Flagged that <code>days_since_last_visit</code> and <code>active_medication_count</code> use <code>current_date</code>, making the table non-deterministic. Recommended documenting refresh cadence.</td>
</tr>
<tr>
<td><strong>Tag enforcement</strong></td>
<td>Not mentioned</td>
<td>Recommended CI check to prevent <code>restricted</code>-tagged models from being referenced by non-restricted downstream models.</td>
</tr>
<tr>
<td><strong>Risk tier thresholds</strong></td>
<td>Suggested making thresholds dbt vars</td>
<td>Used different (more conservative) thresholds: high tier requires <code>&gt;=5 encounters AND &gt;=3 diagnoses</code> (AND logic), vs. Claude’s <code>&gt;=10 encounters OR &gt;=5 diagnoses</code> (OR logic). Medium tier in both used OR logic.</td>
</tr>
</tbody></table>
<p><strong>Why this matters:</strong> Claude Code offered textbook advice: reasonable, but generic. Altimate Code's recommendations were actionable at the PR level: a specific YAML annotation for Safe Harbor, a specific CI check for tag containment, a specific warning about non-deterministic columns that would produce different results depending on when the pipeline runs.</p>
<p>These are the details that prevent a compliance review from becoming a compliance finding.</p>
<hr />
<h2>The Extra Steps Altimate Code Took</h2>
<p>These are capabilities that Claude Code simply does not have access to:</p>
<table>
<thead>
<tr>
<th>Tool Used</th>
<th>What It Did</th>
<th>Why It Matters</th>
</tr>
</thead>
<tbody><tr>
<td><code>altimate_core_classify_pii</code></td>
<td>Automated PII scan on the final schema — flagged <code>patient_id</code> (0.75 confidence) and <code>date_of_birth</code> (0.9 confidence) as remaining quasi-identifiers</td>
<td>Catches PII that humans miss in code review</td>
</tr>
<tr>
<td><code>lineage_check</code></td>
<td>Traced column-level lineage from sources through CTEs to output</td>
<td>Caught <code>full_name</code> leaking through a CTE even though it wasn’t in final SELECT</td>
</tr>
<tr>
<td><code>impact_analysis</code></td>
<td>Automated blast radius calculation across the full DAG</td>
<td>Confirms safety with certainty, not guessing</td>
</tr>
<tr>
<td><code>altimate_core_schema_diff</code></td>
<td>Column-level before/after diff with breaking change classification</td>
<td>Documents exactly what changes for downstream consumers</td>
</tr>
<tr>
<td><code>sql_execute</code> (warehouse)</td>
<td>Queried actual Snowflake tables to verify data distribution</td>
<td>Validates that the model produces clinically sensible results</td>
</tr>
<tr>
<td><code>altimate-dbt build</code></td>
<td>Full project build + test execution on Snowflake</td>
<td>Proves the code actually works, not just “looks right”</td>
</tr>
</tbody></table>
<hr />
<h2>Summary: The Scorecard</h2>
<table>
<thead>
<tr>
<th>Capability</th>
<th>Claude Code (Opus 4.6)</th>
<th>Altimate Code (Opus 4.6)</th>
</tr>
</thead>
<tbody><tr>
<td>SQL generation quality</td>
<td>Good structure, but used phantom columns</td>
<td>Verified against actual schema — builds cleanly</td>
</tr>
<tr>
<td>PII handling</td>
<td>Masked (hash) — PII still in pipeline</td>
<td>Eliminated — PII never enters the query</td>
</tr>
<tr>
<td>Build verification</td>
<td>Not attempted</td>
<td>Built + tested on Snowflake (PASS=40)</td>
</tr>
<tr>
<td>Data validation</td>
<td>None</td>
<td>Queried warehouse, verified distribution</td>
</tr>
<tr>
<td>Downstream impact</td>
<td>Manual guess about one view</td>
<td>Automated blast radius + schema diff (16 changes, 6 breaking)</td>
</tr>
<tr>
<td>PII audit</td>
<td>None</td>
<td>Automated scan with confidence scores</td>
</tr>
<tr>
<td>Column-level lineage</td>
<td>Not performed</td>
<td>Traced end-to-end, caught PII leak in CTE</td>
</tr>
<tr>
<td>Governance recommendations</td>
<td>Generic HIPAA mention</td>
<td>Specific: RBAC, Safe Harbor age-banding, non-determinism, CI tag enforcement</td>
</tr>
<tr>
<td>Would the model build?</td>
<td>No — missing column references</td>
<td>Yes — full project green</td>
</tr>
</tbody></table>
<h2>In Conclusion: An AI Coding Assistant Needs a Domain Expert Harness to Master Data Engineering</h2>
<p>The takeaway of all this is that <strong>general-purpose AI + domain-specific intelligence</strong> produces categorically better results than either alone. For data engineering work where correctness, compliance, and safety matter, the domain layer is not optional.</p>
<p>Altimate Code's value is not that it replaces Claude Code Its value is that it surrounds Claude Code with 100+ specialized tools that verify, build, test, scan, and validate before declaring the job done. For data engineering teams shipping to production, that difference is the entire gap between "looks right" and "is right."</p>
<hr />
<h2>Steps To Reproduce This Analysis</h2>
<p><strong>We’ve open-sourced the full analysis so you can reproduce it:</strong></p>
<p><strong>Repository:</strong> <a href="https://github.com/altimateanas/altimate_code_enterprise_demos">github.com/altimateanas/altimate_code_enterprise_demos</a></p>
<ol>
<li><p>Clone the repo: <code>git clone https://github.com/altimateanas/altimate_code_enterprise_demos</code></p>
</li>
<li><p>Navigate to <code>medflow-analytics/</code>directory It's a healthcare dbt project running on Snowflake with patient data, claims, encounters, diagnoses, medications, and lab results.</p>
</li>
<li><p>Setup your snowflake target in dbt profiles.yml.</p>
</li>
<li><p>Run the prompt in section "The Experiment: Claude Code vs. Altimate Code" in Claude Code (standalone) then observe the output</p>
</li>
<li><p>Connect Altimate Code and run the same prompt and compare</p>
</li>
</ol>
<p><strong>Make sure to use the same underlying LLM in both runs.</strong></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/claude-code-or-altimate-code-for-data-engineering/a5d2ee61-e0d3-4b90-9909-376d54ed2949.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>We built AI that actually works for data engineering.  We crushed the ADE benchmark.</title>
    <link>https://altimate.ai/blog/introducing-altimate-code</link>
    <guid isPermaLink="true">https://altimate.ai/blog/introducing-altimate-code</guid>
    <pubDate>Thu, 19 Mar 2026 15:58:52 GMT</pubDate>
    <dc:creator>Anand Gupta</dc:creator>
    <category>AI Tool </category>
    <category>data-engineering</category>
    <category>altimateAI</category>
    <description>tl;dr : Today, we are launching Altimate Code, an open-source agentic data engineering harness that far exceeds generic LLMs (and other leading models) on data engineering tasks. Check out the project</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/introducing-altimate-code/04d44fc2-99f4-442b-9df5-80debde510b6.jpg" alt="We built AI that actually works for data engineering.  We crushed the ADE benchmark." /></p>
<p>tl;dr : Today, we are launching Altimate Code, an open-source agentic data engineering harness that far exceeds generic LLMs (and other leading models) on data engineering tasks. <a href="https://github.com/AltimateAI/altimate-code">Check out the project on GitHub</a>, or catch the <a href="https://www.youtube.com/watch?v=g-ACWwz9TGg">March 25th overview and AMA on YouTube</a>.</p>
<hr />
<p>AI agents have transformed how software gets built. But for data engineering, they have fallen short…</p>
<p>An AI coding agent on Replit <a href="https://fortune.com/2025/07/23/ai-coding-tool-replit-wiped-database-called-it-a-catastrophic-failure/">deleted an entire production database</a> during a code freeze, then <a href="https://www.eweek.com/news/replit-ai-coding-assistant-failure/">created 4,000 fake records</a> to fill the empty tables. An <a href="https://www.atscale.com/blog/troubleshooting-snowflake-cortext-analyst/">independent evaluation</a> of Snowflake's Cortex Analyst found 38% logical accuracy. Six out of ten queries were wrong, but compiled and ran just fine. One team got a <a href="https://seemoredata.io/blog/snowflake-cortex-ai/">$5,000 bill from a single Cortex AI query</a> their resource monitors never caught. <a href="https://medium.com/tr-labs-ml-engineering-blog/is-your-ai-agent-lying-with-perfect-sql-3a6a7d69bccf">78% of AI-generated SQL errors are silent wrong joins</a>, queries that return confidently incorrect data.</p>
<p>These aren't edge cases. They're what happens when AI agents operate on data infrastructure without safety layers. No schema validation, no lineage, no cost controls, no permission enforcement. The agent doesn't know your schema. It can't trace what breaks downstream. It doesn't know what a query will cost. And the system prompt telling it "don't drop tables" stops working at 100K context tokens.</p>
<p>The problem isn't the model. It's everything around it.</p>
<h2>The missing layer</h2>
<p>General-purpose coding agents treat SQL like application code. It isn't. SQL operates on schemas that change, across dialects that diverge on every function name, through lineage chains no LLM can reliably trace, with cost implications that scale to thousands of dollars per mistake.</p>
<p>What data engineering needs is a layer of compiled, deterministic tools that operate <em>outside</em> the LLM's reasoning loop. Tools that validate SQL against your actual schema in 2ms, trace column-level lineage through CTEs deterministically, and catch anti-patterns with zero false positives. Not better prompts. Better engines.</p>
<p>That's what we built.</p>
<h2>Introducing Altimate Code</h2>
<p>Today we're open-sourcing <strong>Altimate Code,</strong> a data engineering harness built on <a href="https://github.com/anomalyco/opencode">OpenCode</a>, the open-source coding agent. Built by the team behind <a href="https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-dbt-power-user">dbt Power User</a>, the most widely used dbt VS Code extension.</p>
<p>The core idea: <strong>the LLM reasons; compiled engines validate; neither replaces the other.</strong></p>
<p>We ran dbt Labs' <a href="https://www.getdbt.com/blog/ade-bench-dbt-data-benchmarking">ADE-bench</a>, the open standard for measuring AI agents on real data engineering tasks.</p>
<img src="/blog/introducing-altimate-code/a6f9a3ac-6eb4-4595-aa45-35c20c3ecbcc.png" alt="" style="display:block;margin:0 auto" />

<p><strong>A cheaper model with compiled tools outperformed a more expensive model without them.</strong> The difference isn't the model. It's the harness. Further details can be found <a href="https://www.altimate.sh/benchmarks">here</a>.</p>
<h2>What the harness catches</h2>
<img src="/blog/introducing-altimate-code/c7510620-d478-417c-b2f9-18f716b81447.png" alt="" style="display:block;margin:0 auto" />

<p>Your agent writes a query. Before it touches your warehouse:</p>
<p>The wrong table name that would have triggered a 30-second Snowflake error? <strong>Caught in 2ms</strong> with a fix suggestion. Five agent fix cycles cost 10ms and not 2.5 minutes of warehouse round-trips.</p>
<p>The cartesian join that would have silently inflated your numbers by 100x? <strong>Caught before execution.</strong> 26 compiled anti-pattern rules, zero false positives across 1,077 benchmark queries.</p>
<p>The column your downstream dashboard depends on? <strong>Traced to its source</strong> through every JOIN, CTE, and subquery with 100% edge match on 500 benchmark queries. The agent reasons on verified lineage, not guesses.</p>
<p>The PII in the staging table you're about to expose? <strong>Flagged and masked.</strong> The SQL injection hiding in a Jinja template? <strong>Blocked.</strong></p>
<p>All compiled. All deterministic. All in milliseconds.</p>
<h2>Making the harness your own</h2>
<p>Engines are the foundation. But what makes Altimate Code <em>yours</em> is what you build on top of them.</p>
<p><strong>Persistent memory</strong> spans across sessions in two scopes: global (your preferences) and project (team knowledge versioned in git). Tell the agent "we never use FLOAT for money columns"… it remembers. Next session, next teammate, the knowledge is there. When one engineer corrects the agent, every teammate inherits the fix on <code>git pull</code>. No Slack message. No wiki update. The correction just propagates.</p>
<p><strong>Governed agent modes</strong> enforce permissions at the engine level, not through prompt instructions that models ignore at long context lengths. The Analyst can't INSERT, UPDATE, DELETE, or DROP. Not because of a system prompt, but because the compiled engine won't execute it. The Builder gets full read/write with your SQL rules applied. The Planner maps tasks without executing.</p>
<p><strong>The compactor</strong> summarizes long sessions while preserving data engineering state: warehouse connections, schema context, dbt project state, lineage findings. Multi-hour sessions maintain continuity across compaction boundaries.</p>
<p><strong>The tracer</strong> captures every LLM call, tool invocation, and warehouse metric locally. No external services. No data leaving your machine. Run <code>/trace</code> for an interactive viewer.</p>
<h2>Why independent?</h2>
<p>Snowflake shipped <a href="https://www.snowflake.com/en/blog/cortex-code-cli-expands-support/">Cortex Code</a>. Databricks launched <a href="https://www.databricks.com/blog/introducing-genie-code">Genie Code</a>. Both recognized that general-purpose agents don't work for data. But both shipped solutions that suit their ecosystem.</p>
<p>Cortex Code won't help you migrate <em>off</em> Snowflake and onto BigQuery. Genie Code is not designed to optimize a Redshift query. Your Airflow DAGs don't run inside Databricks. Your warehouses span multiple providers. Your governance crosses every platform boundary. Your AI agents should too.</p>
<p>Altimate Code connects to Snowflake, BigQuery, Databricks, PostgreSQL, Redshift, DuckDB, MySQL, SQL Server, Oracle, and SQLite. It runs with Anthropic, OpenAI, Google, AWS Bedrock, Azure, Ollama, and OpenRouter. With local models and the local-only tracer, it runs fully air-gapped so no data leaves your machine.</p>
<p>Platform agents will always have telemetry we can't access. We'll always have independence they can't offer. Neither Snowflake nor Databricks will build first-class support for the other's warehouse. Neither will tell your agent a query is unnecessary when their revenue depends on you running it.</p>
<p>Your harness should be yours.</p>
<h2>Try it</h2>
<pre><code class="language-plaintext">npm install -g @altimateai/altimate-code
altimate /discover
</code></pre>
<p>Two commands. It auto-detects your warehouse, indexes your schema, and you're building.</p>
<p>Open source on <a href="https://github.com/AltimateAI/altimate-code">GitHub</a>. Docs at <a href="http://altimate-code.sh">altimate-code.sh</a>. Ten data stores. Any LLM. No platform tax.</p>
<h2>What we're building next, and where you can help</h2>
<p>The compiled engines ship today. Here's where we're headed and where we need the community:</p>
<p><strong>Pipeline monitoring</strong> for Airflow and Dagster. We want this to be proactive, not just interactive.</p>
<p><strong>Blast radius analysis.</strong> Before the agent acts, show what breaks downstream.</p>
<p><strong>Decision memory:</strong> extract <em>why things were built</em> from your Git history so agents stop undoing decisions they don't know were made.</p>
<p><strong>Agent Data sandboxes:</strong> changes prove themselves before touching production and many more</p>
<p>Some of these we'll build. Some of them you'll build first. The roadmap, the benchmarks, and every known gap are in the repo. PRs welcome. Issues welcome. Forks welcome.</p>
<p>We'd rather build this in the open than wait for it to be built inside a walled garden. If you're a data engineer who stitches tools together for a living, come break it.</p>
<h2>Want to learn more or get involved?</h2>
<p>Three options:</p>
<ol>
<li><p><a href="https://github.com/AltimateAI/altimate-code">Check out the project on Github</a> - star the repo to support the project</p>
</li>
<li><p><a href="https://altimate.studio/join-agentic-data-engineering-slack">Join us on Slack</a> - we are launching a new Slack channel for our Agentic Data Engineering efforts. <a href="https://altimate.studio/join-agentic-data-engineering-slack">Join us here</a>.</p>
</li>
<li><p>Sign up for <a href="https://youtube.com/live/g-ACWwz9TGg">next week's live overview and AMA</a> on YouTube.</p>
</li>
</ol>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/introducing-altimate-code/04d44fc2-99f4-442b-9df5-80debde510b6.jpg" type="image/jpeg" />
  </item>
  <item>
    <title>Teaching Claude Code the Art of Data Engineering: Introducing Altimate Skills</title>
    <link>https://altimate.ai/blog/teaching-claude-code-the-art-of-data-engineering-introducing-altimate-skills</link>
    <guid isPermaLink="true">https://altimate.ai/blog/teaching-claude-code-the-art-of-data-engineering-introducing-altimate-skills</guid>
    <pubDate>Thu, 22 Jan 2026 20:31:04 GMT</pubDate>
    <dc:creator>Anand Gupta</dc:creator>
    <category>datamates</category>
    <category>altimate</category>
    <category>data-engineering</category>
    <category>AI skills</category>
    <category>aiskills</category>
    <category>snowflake</category>
    <category>dbt</category>
    <category>altimateAI</category>
    <category>AI</category>
    <category>claude.ai</category>
    <category>claude-code</category>
    <category>genai</category>
    <description>Today, we&apos;re open-sourcing Altimate Skills — a collection of Claude Code skills specifically designed for analytics engineers. We are starting with skills for dbt and Snowflake. These encode the workf</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/teaching-claude-code-the-art-of-data-engineering-introducing-altimate-skills/1048fa9e-42f7-45d3-b2e8-47db897f7d4b.jpeg" alt="Teaching Claude Code the Art of Data Engineering: Introducing Altimate Skills" /></p>
<hr />
<p>Today, we're open-sourcing <strong>Altimate Skills</strong> — a collection of <a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview">Claude Code skills</a> specifically designed for analytics engineers. We are starting with skills for dbt and Snowflake. These encode the workflows and best practices that transform AI from a basic code generator into a capable data engineering assistant.</p>
<p><a class="embed-card" href="https://youtu.be/kvIo5PmF0Ns">https://youtu.be/kvIo5PmF0Ns</a></p>

<p><strong>Key Results:</strong></p>
<ul>
<li><p><strong>+25% improvement</strong> on model creation tasks (40% → 65%)</p>
</li>
<li><p><strong>+22% faster execution</strong> (TPC-H 1TB) with 100% logically equivalent queries generated for SQL optimization.</p>
</li>
<li><p><strong>53% accuracy</strong> on <a href="https://github.com/dbt-labs/ade-bench">ADE-bench</a> (43 real-world dbt tasks)</p>
</li>
<li><p>Skills that actually <strong>teach Claude <em>how</em> to work</strong>, not just <em>what</em> to write</p>
</li>
</ul>
<pre><code class="language-bash"># Get started in 30 seconds
/plugin marketplace add AltimateAI/data-engineering-skills
/plugin install dbt-skills@data-engineering-skills
</code></pre>
<p><strong>GitHub:</strong> <a href="https://github.com/AltimateAI/data-engineering-skills">https://github.com/AltimateAI/data-engineering-skills</a> and ⭐ the repo.</p>
<hr />
<h2>Solving the C<strong>ontext and Workflow Issue</strong></h2>
<p>If you've used Claude Code, Cursor, or any AI coding assistant for dbt development, you've experienced the frustration:</p>
<p><strong>The task:</strong> "Create a staging model for the Stripe payment source."</p>
<p><strong>What you expect:</strong></p>
<pre><code class="language-sql">-- models/staging/stripe/stg_stripe__payments.sql
{{
  config(
    materialized='view',
    schema='staging'
  )
}}

with source as (
    select * from {{ source('stripe', 'payments') }}
),

renamed as (
    select
        id as payment_id,
        amount_cents / 100.0 as amount,
        currency,
        status,
        created_at
    from source
)

select * from renamed
</code></pre>
<p><strong>What you get:</strong></p>
<pre><code class="language-sql">SELECT * FROM {{ source('stripe', 'payments') }}
</code></pre>
<p>No <code>stg_</code> prefix. No <code>{{ source() }}</code> reference. No config block. No CTEs. No understanding of your project's conventions.</p>
<h3>Why This Happens</h3>
<p>The core issue isn't that LLMs lack knowledge — Claude knows dbt syntax perfectly well. The problem is <strong>context and workflow</strong>:</p>
<ol>
<li><p><strong>No project awareness</strong> — Claude doesn't know your naming conventions, folder structure, or existing patterns</p>
</li>
<li><p><strong>No verification loop</strong> — Claude declares "done" after writing code, without running <code>dbt build</code></p>
</li>
<li><p><strong>No convention discovery</strong> — Claude guesses at patterns instead of reading existing models first</p>
</li>
<li><p><strong>Compile ≠ Success</strong> — <code>dbt compile</code> passes, but the model produces the wrong output</p>
</li>
</ol>
<p>This leads to a frustrating cycle: AI writes code → You review and fix → AI loses context → Repeat.</p>
<hr />
<h2>What Are Claude Code Skills?</h2>
<p>Anthorpic introduced <a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview">Claude Skills</a> in October 2025. Skills are markdown files that teach Claude <strong>how to approach tasks</strong>, not just what syntax to use. Think of them as encoding the workflow an experienced analytics engineer follows.</p>
<p>Skills matter because they make Claude more reliable and specialized: you can standardize repeatable work (like formatting outputs, following internal conventions, or running a known process) and reuse it across projects. Claude can also load Skills progressively, starting with lightweight metadata and pulling in deeper instructions only when needed, giving you targeted behavior without bloating context.</p>
<p>Practically, a Skill is typically packaged as a small folder of structured instructions (and optionally templates, scripts, or reference files) that define <em>how</em> Claude should approach a workflow. See our <a href="https://github.com/AltimateAI/data-engineering-skills">data-engineering-skills</a> repo folders as an example.</p>
<p>A skill has two parts:</p>
<p><strong>1. Trigger conditions</strong> — When should this skill activate?</p>
<pre><code class="language-yaml">---
name: creating-dbt-models
description: |
  Guide for creating dbt models. ALWAYS use this skill when:
  (1) Creating ANY new model (staging, intermediate, mart)
  (2) Task mentions "create", "build", "add" with model/table
  (3) Modifying model logic or columns
---
</code></pre>
<p><strong>2. Workflow instructions</strong> — What steps should Claude follow?</p>
<pre><code class="language-markdown"># dbt Model Development

**Read before you write. Build after you write. Verify your output.**

## Critical Rules
1. ALWAYS run `dbt build` after creating models - compile is NOT enough
2. ALWAYS verify output after build using `dbt show`
3. If build fails 3+ times, stop and reassess your approach

## Workflow
### 1. Understand Requirements
- What columns are needed?
- What is the grain (one row per what)?
- What calculations are required?

### 2. Discover Project Conventions
cat dbt_project.yml
find models/ -name "*.sql" | head -20
Read 2-3 existing models to learn patterns...
</code></pre>
<p>When Claude encounters a task that matches the trigger conditions, it automatically applies the skill's workflow.</p>
<hr />
<h2>The Skills We Built</h2>
<h3><a href="https://github.com/AltimateAI/data-engineering-skills/tree/main/skills/dbt">dbt Skills</a></h3>
<table>
<thead>
<tr>
<th>Skill</th>
<th>Purpose</th>
<th>Key Behaviors</th>
</tr>
</thead>
<tbody><tr>
<td><strong>creating-dbt-models</strong></td>
<td>Model creation</td>
<td>Convention discovery → Write → Build → Verify output</td>
</tr>
<tr>
<td><strong>debugging-dbt-errors</strong></td>
<td>Error troubleshooting</td>
<td>Read full error → Check upstream → Apply fix → Rebuild</td>
</tr>
<tr>
<td><strong>testing-dbt-models</strong></td>
<td>Schema tests</td>
<td>Study existing test patterns → Match project style</td>
</tr>
<tr>
<td><strong>documenting-dbt-models</strong></td>
<td>Documentation</td>
<td>Analyze model → Generate descriptions</td>
</tr>
<tr>
<td><strong>migrating-sql-to-dbt</strong></td>
<td>Legacy SQL conversion</td>
<td>Parse SQL → Create proper dbt model</td>
</tr>
<tr>
<td><strong>refactoring-dbt-models</strong></td>
<td>Safe restructuring</td>
<td>Track dependencies → Apply changes → Verify downstream</td>
</tr>
</tbody></table>
<h3><a href="https://github.com/AltimateAI/data-engineering-skills/tree/main/skills/snowflake">Snowflake Skills</a></h3>
<table>
<thead>
<tr>
<th>Skill</th>
<th>Purpose</th>
<th>Key Behaviors</th>
</tr>
</thead>
<tbody><tr>
<td><strong>optimizing-query-text</strong></td>
<td>Performance tuning (from SQL)</td>
<td>Profile query → Identify bottlenecks → Apply patterns</td>
</tr>
<tr>
<td><strong>optimizing-query-by-id</strong></td>
<td>Performance tuning (from query ID)</td>
<td>Fetch query from history → Analyze → Optimize</td>
</tr>
<tr>
<td><strong>finding-expensive-queries</strong></td>
<td>Cost analysis</td>
<td>Query ACCOUNT_USAGE → Identify top spenders</td>
</tr>
</tbody></table>
<hr />
<h2>Deep Dive: How creating-dbt-models Changes Claude's Behavior</h2>
<p>Let's trace through a real task from our benchmark to see the difference.</p>
<blockquote>
<h3>Task: "Create a model called dim_customer that renames id to customer_id and makes it a unique primary key."</h3>
</blockquote>
<h3>Without Skills (Baseline Claude)</h3>
<p><strong>Claude's approach:</strong></p>
<ol>
<li>Write the SQL immediately:</li>
</ol>
<pre><code class="language-sql">SELECT
  id AS customer_id,
  *
FROM customers
</code></pre>
<ol>
<li><p>Run <code>dbt compile</code> → passes</p>
</li>
<li><p>Declare done</p>
</li>
</ol>
<p><strong>Outcome:</strong> Model compiles, but:</p>
<ul>
<li><p>Wrong table reference (raw table vs staging model)</p>
</li>
<li><p>No config block matching project patterns</p>
</li>
<li><p>No verification that the output is correct</p>
</li>
<li><p>No <code>unique</code> test added for primary key</p>
</li>
</ul>
<h3>With creating-dbt-models Skill</h3>
<p>(<a href="https://github.com/AltimateAI/data-engineering-skills/tree/main/skills/dbt/creating-dbt-models">See the specific SKILL.md file here</a>)</p>
<p><strong>Claude's approach:</strong></p>
<p><strong>Step 1: Understand Requirements</strong></p>
<ul>
<li><p>Columns needed: <code>customer_id</code> (renamed from <code>id</code>), plus all other columns</p>
</li>
<li><p>Grain: One row per customer</p>
</li>
<li><p>Constraint: Must be unique on <code>customer_id</code></p>
</li>
</ul>
<p><strong>Step 2: Discover Project Conventions</strong></p>
<pre><code class="language-bash">$ cat dbt_project.yml
# Shows model-paths, naming conventions

$ find models/ -name "*.sql" | head -10
models/staging/stg_customers.sql
models/staging/stg_products.sql
models/marts/dim_products.sql

$ cat models/marts/dim_products.sql
# Learns: CTEs named 'source' and 'final', config blocks, column naming
</code></pre>
<p><strong>Step 3: Find Upstream Models</strong></p>
<pre><code class="language-bash">$ cat models/staging/stg_customers.sql
# Discovers the correct source to reference
</code></pre>
<p><strong>Step 4: Write Model (following discovered patterns)</strong></p>
<pre><code class="language-sql">-- models/marts/dim_customer.sql
{{
  config(
    materialized='table'
  )
}}

with source as (
    select * from {{ ref('stg_customers') }}
),

final as (
    select
        id as customer_id,
        name,
        email,
        created_at
    from source
)

select * from final
</code></pre>
<p><strong>Step 5: Update schema.yml with test</strong></p>
<pre><code class="language-yaml">models:
  - name: dim_customer
    columns:
      - name: customer_id
        tests:
          - unique
          - not_null
</code></pre>
<p><strong>Step 6: Build and Verify</strong></p>
<pre><code class="language-bash">$ dbt build --select dim_customer
# Actually runs the model and tests

$ dbt show --select dim_customer --limit 5
# Verifies output looks correct
</code></pre>
<p><strong>Outcome:</strong> Model matches project conventions, has proper tests, output verified.</p>
<hr />
<h2>Benchmarking: ADE-bench Results</h2>
<p>We evaluated our skills using <a href="https://github.com/dbt-labs/ade-bench">ADE-bench</a>, a framework for evaluating AI agents on analytics engineering tasks created by dbt Labs.</p>
<h3>Test Setup</h3>
<ul>
<li><p><strong>43 tasks</strong> across 5 projects (Airbnb reviews, F1 racing, Asana projects, Analytics engineering, Intercom conversations)</p>
</li>
<li><p><strong>Task types:</strong> Model creation, bug fixing, debugging, refactoring, data analysis</p>
</li>
<li><p><strong>Model:</strong> Claude Sonnet 4.5</p>
</li>
<li><p><strong>Database:</strong> Snowflake</p>
</li>
<li><p><strong>Evaluation:</strong> Automated tests comparing model output to expected results</p>
</li>
</ul>
<h3>Task Difficulty Distribution</h3>
<table>
<thead>
<tr>
<th>Difficulty</th>
<th>Example Task</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Easy</strong></td>
<td>"Fix the surrogate_key deprecation warning."</td>
</tr>
<tr>
<td><strong>Medium</strong></td>
<td>"Create a dim_customer model with unique primary key."</td>
</tr>
<tr>
<td><strong>Hard</strong></td>
<td>"Identify which top-N tables have inconsistent results due to tie.s"</td>
</tr>
</tbody></table>
<h3>Overall Results</h3>
<table>
<thead>
<tr>
<th>Configuration</th>
<th>Accuracy</th>
<th>Tasks Resolved</th>
<th>Avg Runtime</th>
<th>Avg Cost</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline Claude (no skills, no MCP)</td>
<td>46.5%</td>
<td>20/43</td>
<td>152s</td>
<td>$0.33/task</td>
</tr>
<tr>
<td>Claude + Skills</td>
<td>53.5%</td>
<td>23/43</td>
<td>182s</td>
<td>$0.40/task</td>
</tr>
</tbody></table>
<h3>Results by Task Category</h3>
<table>
<thead>
<tr>
<th>Category</th>
<th>Baseline</th>
<th>With Skills</th>
<th>Improvement</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Model Creation</strong></td>
<td>40%</td>
<td>65%</td>
<td><strong>+25 pts</strong></td>
</tr>
<tr>
<td><strong>Bug Fixing</strong></td>
<td>60%</td>
<td>70%</td>
<td>+10 pts</td>
</tr>
<tr>
<td><strong>Debugging</strong></td>
<td>35%</td>
<td>50%</td>
<td>+15 pts</td>
</tr>
<tr>
<td><strong>Refactoring</strong></td>
<td>30%</td>
<td>35%</td>
<td>+5 pts</td>
</tr>
<tr>
<td><strong>Analysis</strong></td>
<td>25%</td>
<td>30%</td>
<td>+5 pts</td>
</tr>
</tbody></table>
<h3>What Worked</h3>
<p><strong>Model creation</strong> saw the biggest improvement. The creating-dbt-models skill's workflow of "discover conventions → write → build → verify" catches errors that baseline Claude misses:</p>
<ol>
<li><p><strong>Convention discovery</strong> prevents wrong naming/structure</p>
</li>
<li><p><strong>Mandatory</strong> <code>dbt build</code> catches runtime errors that <code>compile</code> misses</p>
</li>
<li><p><strong>Output verification</strong> ensures the model produces correct data</p>
</li>
</ol>
<p><strong>Example success — Task</strong> <code>analytics_engineering003</code>:</p>
<blockquote>
<p>"Create a model called 'dim_customer' that renames id to customer_id, and makes that row a unique primary key."</p>
</blockquote>
<ul>
<li><p>Baseline: Created model but wrong column reference, no test</p>
</li>
<li><p>With skills: Discovered existing staging model, matched project patterns, and added proper unique test</p>
</li>
</ul>
<h3>What Didn't Work</h3>
<p><strong>Complex analysis tasks</strong> remain challenging. Tasks requiring deep reasoning about data behavior (like identifying which queries have non-deterministic results due to ties) still need human insight.</p>
<p><strong>Example failure — Task</strong> <code>f1003</code>:</p>
<blockquote>
<p>"Identify which top-N tables have inconsistent results due to ties in the data"</p>
</blockquote>
<p>This task requires:</p>
<ol>
<li><p>Understanding the semantic meaning of "ties"</p>
</li>
<li><p>Analyzing actual data values across 8 models</p>
</li>
<li><p>Reasoning about SQL ordering behavior</p>
</li>
</ol>
<p>Skills can't encode this kind of domain reasoning — they work best for <strong>workflow guidance</strong>, not <strong>analytical judgment</strong>.</p>
<hr />
<h2>The Overhead Trade-off</h2>
<p>Skills add overhead. The "discover conventions" step takes 15-30 seconds of additional LLM calls. Is it worth it?</p>
<table>
<thead>
<tr>
<th>Metric</th>
<th>Without Skills</th>
<th>With Skills</th>
</tr>
</thead>
<tbody><tr>
<td>Avg task time</td>
<td>152 seconds</td>
<td>182 seconds</td>
</tr>
<tr>
<td>Success rate</td>
<td>46.5%</td>
<td>53.5%</td>
</tr>
<tr>
<td>Time to first success</td>
<td>~5-6 min</td>
<td>~3-4 min</td>
</tr>
<tr>
<td>Human intervention needed</td>
<td>High</td>
<td>Low</td>
</tr>
</tbody></table>
<p><strong>Our conclusion:</strong> The 30-second overhead is worth it because:</p>
<ol>
<li><p>Successful tasks need no human review</p>
</li>
<li><p>Failed tasks fail faster (3-failure rule)</p>
</li>
<li><p>Time saved on human review &gt;&gt; time spent on convention discovery</p>
</li>
</ol>
<h2>Benchmarking: SQL Query Optimization</h2>
<p>We evaluated the <code>optimizing-query-text</code> skill on TPC-H SF1000 (1TB dataset).</p>
<h3>Test Setup</h3>
<ul>
<li><p><strong>10 queries</strong> from TPC-H benchmark</p>
</li>
<li><p><strong>Model:</strong> Claude Sonnet 4.5</p>
</li>
<li><p><strong>Evaluation:</strong> Automated comparison of query results + execution time</p>
</li>
</ul>
<h3>Overall Results</h3>
<table>
<thead>
<tr>
<th>Configuration</th>
<th>Pass Rate</th>
<th>Avg Time Improvement</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline Claude (no skills)</td>
<td>80% (8/10)</td>
<td>+25% (on passing queries)</td>
</tr>
<tr>
<td>Claude + Skills</td>
<td><strong>100% (10/10)</strong></td>
<td>+22%</td>
</tr>
</tbody></table>
<h3>What Failed Without Skills</h3>
<p>Baseline failed 2 queries by making "optimizations" that changed what the query returned:</p>
<ul>
<li><p>Changed deduplication behavior, returning extra rows</p>
</li>
<li><p>Renamed columns, breaking downstream compatibility</p>
</li>
</ul>
<hr />
<h2>Installation &amp; Usage</h2>
<h3>Add the Marketplace</h3>
<pre><code class="language-bash">/plugin marketplace add AltimateAI/data-engineering-skills
</code></pre>
<h3>Install Skills</h3>
<p>You can browse and install via the CLI, or directly install plugins:</p>
<pre><code class="language-bash"># Install dbt skills
/plugin install dbt-skills@data-engineering-skills

# Install Snowflake skills
/plugin install snowflake-skills@data-engineering-skills
</code></pre>
<p>After installing, skills activate automatically when you mention relevant tasks.</p>
<h3>Available Skills</h3>
<p><strong>dbt Skills:</strong></p>
<ul>
<li><p><code>creating-dbt-models</code> — Model creation with convention discovery</p>
</li>
<li><p><code>debugging-dbt-errors</code> — Systematic error troubleshooting</p>
</li>
<li><p><code>testing-dbt-models</code> — Schema tests and data quality</p>
</li>
<li><p><code>documenting-dbt-models</code> — Generate descriptions in schema.yml</p>
</li>
<li><p><code>migrating-sql-to-dbt</code> — Convert legacy SQL to dbt models</p>
</li>
<li><p><code>refactoring-dbt-models</code> — Safe restructuring with impact analysis</p>
</li>
</ul>
<p><strong>Snowflake Skills:</strong></p>
<ul>
<li><p><code>optimizing-query-text</code> — Optimize SQL you provide</p>
</li>
<li><p><code>optimizing-query-by-id</code> — Optimize using query ID from history</p>
</li>
<li><p><code>finding-expensive-queries</code> — Find top cost/time queries</p>
</li>
</ul>
<h3>Usage</h3>
<p>Skills activate automatically based on your request:</p>
<table>
<thead>
<tr>
<th>Your Request</th>
<th>Skill Activated</th>
</tr>
</thead>
<tbody><tr>
<td>"Create a new orders model."</td>
<td><code>creating-dbt-models</code></td>
</tr>
<tr>
<td>"Fix this compilation error."</td>
<td><code>debugging-dbt-errors</code></td>
</tr>
<tr>
<td>"Add tests to the customers model."</td>
<td><code>testing-dbt-models</code></td>
</tr>
<tr>
<td>"Document the revenue metrics".</td>
<td><code>documenting-dbt-models</code></td>
</tr>
<tr>
<td>"This query is slow; optimize it."</td>
<td><code>optimizing-query-text</code></td>
</tr>
<tr>
<td>"Why is query X expensive?"</td>
<td><code>optimizing-query-by-id</code></td>
</tr>
<tr>
<td>"What are our most expensive queries?"</td>
<td><code>finding-expensive-queries</code></td>
</tr>
</tbody></table>
<hr />
<h2>Combining Skills with Altimate MCP Tools</h2>
<p>Skills become even more powerful when combined with <a href="https://docs.myaltimate.com/">Altimate's MCP server</a>. The MCP server provides real-time access to your dbt project and data warehouse:</p>
<table>
<thead>
<tr>
<th>MCP Tool</th>
<th>What It Provides</th>
</tr>
</thead>
<tbody><tr>
<td><code>dbt_project_info</code></td>
<td>Project structure, model list, sources</td>
</tr>
<tr>
<td><code>dbt_model_details</code></td>
<td>Column types, dependencies, compiled SQL</td>
</tr>
<tr>
<td><code>dbt_compile</code></td>
<td>Compile models without CLI</td>
</tr>
<tr>
<td><code>snowflake_query_history</code></td>
<td>Recent query executions and stats</td>
</tr>
<tr>
<td><code>snowflake_table_stats</code></td>
<td>Row counts, clustering info</td>
</tr>
</tbody></table>
<p><strong>Example: Skills + MCP workflow</strong></p>
<p>User: "The daily_revenue model is producing wrong numbers."</p>
<p>Claude (with skills + MCP):</p>
<ol>
<li><p><strong>debugging-dbt-errors skill activates</strong></p>
</li>
<li><p>Uses <code>dbt_model_details</code> to get model SQL and dependencies</p>
</li>
<li><p>Uses <code>dbt_compile</code> to check for errors</p>
</li>
<li><p>Queries upstream models to verify input data</p>
</li>
<li><p>Identifies the issue (e.g., missing WHERE clause)</p>
</li>
<li><p>Fixes and rebuilds</p>
</li>
<li><p>Uses <code>dbt show</code> to verify the correct output</p>
</li>
</ol>
<hr />
<h2>What We Learned Building This</h2>
<h3>1. Workflow &gt; Knowledge</h3>
<p>The biggest wins came from encoding <strong>workflows</strong>, not facts. Claude already knows dbt syntax — what it lacks is the discipline to:</p>
<ul>
<li><p>Check existing patterns before writing</p>
</li>
<li><p>Run <code>dbt build</code> instead of <code>dbt compile</code></p>
</li>
<li><p>Verify output after build</p>
</li>
</ul>
<h3>2. The 3-Failure Rule</h3>
<p>We added this to every skill:</p>
<blockquote>
<p>"If build fails 3+ times, STOP. Step back and reassess your entire approach."</p>
</blockquote>
<p>This prevents Claude from making tiny tweaks hoping they work. Instead, it forces a fundamental rethink.</p>
<h3>3. Skills Can't Replace Domain Expertise</h3>
<p>Skills work best for <strong>procedural tasks</strong> with clear success criteria. They struggle with:</p>
<ul>
<li><p>Tasks requiring business context</p>
</li>
<li><p>Ambiguous requirements ("make this better")</p>
</li>
<li><p>Deep analytical reasoning about data behavior</p>
</li>
</ul>
<h3>4. Convention Discovery Is Essential</h3>
<p>The #1 source of Claude errors was mismatched conventions. Simply adding "read 2-3 existing models first" eliminated most of these.</p>
<hr />
<h2>What's Next</h2>
<p>We're actively developing:</p>
<ul>
<li><p><strong>Airflow skills</strong> — DAG development, debugging, testing</p>
</li>
<li><p><strong>Cross-platform migration</strong> — dbt ↔ SQL Server, Oracle</p>
</li>
<li><p><strong>Snowflake cost optimization</strong> — Warehouse sizing, query patterns</p>
</li>
<li><p><strong>Data quality workflows</strong> — Anomaly detection, freshness checks</p>
</li>
</ul>
<h3>Contributing</h3>
<p>Altimate Skills is open source (MIT License). We welcome:</p>
<ul>
<li><p><strong>New skills</strong> for workflows we haven't covered</p>
</li>
<li><p><strong>Improvements</strong> to existing skills based on your team's patterns</p>
</li>
<li><p><strong>Benchmark results</strong> on different datasets</p>
</li>
</ul>
<p><strong>GitHub:</strong> <a href="https://github.com/AltimateAI/data-engineering-skills">https://github.com/AltimateAI/data-engineering-skills</a></p>
<hr />
<h2>Try It Now</h2>
<pre><code class="language-bash"># Add the marketplace
/plugin marketplace add AltimateAI/altimate-skills

# Install the plugins you need
/plugin install dbt-skills@altimate-skills
/plugin install snowflake-skills@altimate-skills
</code></pre>
<p><strong>Resources:</strong></p>
<ul>
<li><p><a href="https://github.com/AltimateAI/data-engineering-skills">GitHub Repository</a> and ⭐ the repo.</p>
</li>
<li><p><a href="https://docs.myaltimate.com/">Altimate MCP Server Docs</a></p>
</li>
<li><p><a href="https://github.com/dbt-labs/ade-bench">ADE-bench Framework</a></p>
</li>
<li><p><a href="https://app.slack.com/client/T0VLPD22H/C05KPDGRMDW">dbt Slack #tools-dbt-power-user</a></p>
</li>
</ul>
<hr />
<p><em>Built by the team at</em> <a href="https://altimate.ai/"><em>Altimate AI</em></a> <em>— Making data engineering delightful.</em></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/teaching-claude-code-the-art-of-data-engineering-introducing-altimate-skills/1048fa9e-42f7-45d3-b2e8-47db897f7d4b.jpeg" type="image/jpeg" />
  </item>
  <item>
    <title>Adaptive Compute vs. Auto Tune: A Practical Guide to Optimizing Snowflake Warehouses</title>
    <link>https://altimate.ai/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses</link>
    <guid isPermaLink="true">https://altimate.ai/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses</guid>
    <pubDate>Wed, 30 Jul 2025 22:41:32 GMT</pubDate>
    <dc:creator>Dana Van Aken</dc:creator>
    <category>altimateAI</category>
    <category>data-engineering</category>
    <category>snowflake</category>
    <category>Snowflake performance</category>
    <category>data-warehousing</category>
    <description>Managing Snowflake warehouses efficiently is a constant balancing act. Set them too large, and you&apos;re burning money on idle compute. Too small, and your queries slow to a crawl, frustrating users and missing SLAs. For many organizations, this manual ...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/6da7cca8-4c24-457a-80da-e02f4eb8bff6.jpeg" alt="Adaptive Compute vs. Auto Tune: A Practical Guide to Optimizing Snowflake Warehouses" /></p>
<p>Managing Snowflake warehouses efficiently is a constant balancing act. Set them too large, and you're burning money on idle compute. Too small, and your queries slow to a crawl, frustrating users and missing SLAs. For many organizations, this manual tuning process is time-consuming while still leaving significant cost savings on the table.</p>
<p>Two solutions promise to solve this challenge in very different ways: Snowflake's new <strong>Adaptive Compute</strong> eliminates warehouse management complexity entirely, while <strong>Altimate AI's Auto Tune</strong> brings intelligent automation to standard warehouses with granular cost controls. This guide breaks down how each works, their tradeoffs, and which to choose based on your specific needs.</p>
<h1 id="heading-what-is-adaptive-compute">What is Adaptive Compute?</h1>
<p>Today, managing Snowflake warehouses requires juggling multiple decisions: choosing the right size (X-Small through 6X-Large), configuring cluster policies, setting auto-suspend timers, and more. Get these wrong, and you're likely to be overpaying for idle compute or suffering from poor query performance.</p>
<p><strong>Adaptive Compute</strong> changes this equation entirely. Instead of fixed-size warehouses, <strong>Adaptive Warehouses</strong> act as pointers to a shared, elastic compute pool that Snowflake manages behind the scenes. When you submit a query to an Adaptive Warehouse, Snowflake automatically:</p>
<ul>
<li><p>Analyzes the query plan and resource requirements</p>
</li>
<li><p>Allocates the right amount of compute from the shared pool</p>
</li>
<li><p>Routes the query to available resources</p>
</li>
<li><p>Scales compute up or down based on actual needs</p>
</li>
</ul>
<p>Think of it like switching from buying dedicated servers to using serverless functions – you stop worrying about infrastructure and focus on your workloads.</p>
<p><img src="/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/448aedd0-9d02-4f34-8bd9-e292885bf9c2.png" alt="With Adaptive Warehouses, customers still interact with named warehouses, but under the hood, each warehouse is simply a pointer to a shared compute pool within the account. Queries are automatically routed to appropriately sized compute clusters based on their resource needs and availability." class="image--center mx-auto" /></p>
<p><strong><em>Figure 1:</em></strong> <em>With Adaptive Warehouses, customers still interact with named warehouses, but under the hood, each warehouse is simply a pointer to a shared compute pool within the account. Queries are automatically routed to appropriately sized compute clusters based on their resource needs and availability.</em></p>
<h3 id="heading-from-many-settings-to-just-two">From Many Settings to Just Two</h3>
<p>Snowflake’s standard warehouses require configuring multiple parameters:</p>
<ul>
<li><p>Warehouse size</p>
</li>
<li><p>Minimum and maximum cluster count</p>
</li>
<li><p>Scaling policy (Standard or Economy)</p>
</li>
<li><p>Auto-suspend timing</p>
</li>
<li><p>Auto-resume behavior</p>
</li>
<li><p>Query Acceleration</p>
</li>
</ul>
<p>Adaptive Compute replaces all of these with just two settings:</p>
<ol>
<li><p><strong>Warehouse Credit Limit:</strong> The maximum credits the warehouse can consume per hour. This acts as your primary control lever, determining how many concurrent queries can run based on their compute requirements. When the warehouse reaches its credit limit, additional queries are queued until resources become available.</p>
</li>
<li><p><strong>Target Statement Size (temporary):</strong> An optional hint about your expected query sizes. Currently, Adaptive Compute only supports scaling down for smaller queries, and this setting defines the maximum target size. Note that Snowflake intends to deprecate this setting once Adaptive Compute’s autoscaling capabilities mature[<a class="post-section-overview" href="#references-section">1</a>], so don’t build processes around it.</p>
</li>
</ol>
<p><img src="/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/44797494-87ad-4e37-ac25-fb978775b24c.png" alt class="image--center mx-auto" /></p>
<p><strong><em>Figure 2:</em></strong> <em>Adaptive Compute reduces configuration complexity by replacing multiple tuning settings with just two controls: a Warehouse Credit Limit and an optional Target Statement Size.</em></p>
<p>If you convert a standard warehouse to Adaptive, Snowflake sets the initial Warehouse Credit Limit based on the formula: <code>Warehouse Credit Limit = Current Warehouse Size Credits × Max Cluster Count</code>.</p>
<p>It also sets the Target Statement Size equal to the original warehouse size.</p>
<p>For example, if you convert a Large warehouse (8 credits/hour) with <code>max_clusters=4</code> to Adaptive, you get:</p>
<ul>
<li><p><strong>Warehouse Credit Limit:</strong> 32 credits/hour (8 credits × 4 clusters)</p>
</li>
<li><p><strong>Target Statement Size:</strong> Large</p>
</li>
</ul>
<p>Your Adaptive warehouse can then concurrently run queries totaling up to 32 credits per hour; for example, four Large queries, sixteen Small queries, or any combination fitting within the credit limit.</p>
<h1 id="heading-where-adaptive-compute-delivers">Where Adaptive Compute Delivers</h1>
<h3 id="heading-simplified-infrastructure-management"><strong>Simplified Infrastructure Management</strong></h3>
<p>Adaptive Compute removes much of the manual setup required to manage Snowflake warehouses, freeing up data teams to concentrate on driving business outcomes and delivering innovation. This hands-off model is especially beneficial for platform teams managing large fleets of warehouses, and less technical users who don’t want to think about warehouse tuning.</p>
<h3 id="heading-smarter-resource-allocation"><strong>Smarter Resource Allocation</strong></h3>
<p>Because Snowflake's optimizer has access to detailed query plan metadata (e.g., estimated row counts, join strategies, data volumes), it can predict resource needs more accurately than external tools. Assigning just enough CPU and memory per query also reduces the likelihood of over-provisioning.</p>
<p><strong>Example scenario:</strong> Two very different queries are submitted to the same Adaptive Warehouse simultaneously:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Query</strong></td><td><strong>Description</strong></td><td><strong>Predicted Compute Needs</strong></td></tr>
</thead>
<tbody>
<tr>
<td>A</td><td>Complex 5-way join with 100M rows</td><td>Gets Large-sized compute</td></tr>
<tr>
<td>B</td><td>Simple filter on 1000 rows</td><td>Gets X-Small-sized compute</td></tr>
</tbody>
</table>
</div><p>As shown in the table, Adaptive Compute predicts greater compute needs for the Query A (the heavier query) than Query B (the simpler query).</p>
<h3 id="heading-seamless-conversion-from-standard-warehouses"><strong>Seamless Conversion from Standard Warehouses</strong></h3>
<p>Converting to Adaptive Compute is simple and requires no downtime:</p>
<p><code>ALTER WAREHOUSE my_warehouse SET TYPE = 'ADAPTIVE';</code></p>
<p>Running queries complete on the old compute while new queries immediately use adaptive resources. There’s no need to update connection strings, modify scripts, or coordinate downtime windows.</p>
<h3 id="heading-solving-warehouse-sprawl"><strong>Solving Warehouse Sprawl</strong></h3>
<p>A common issue is warehouse sprawl, where companies create separate warehouses for different teams, workload types, or usage patterns. For example, a marketing team might operate five different warehouses:</p>
<ul>
<li><p><code>MARKETING_REPORTS_L</code> (idle 22 hours/day)</p>
</li>
<li><p><code>MARKETING_ETL_XL</code> (runs 2 hours nightly)</p>
</li>
<li><p><code>MARKETING_DASHBOARD_L</code> (idle 20 hours/day)</p>
</li>
<li><p><code>MARKETING_ADHOC_M</code> (sporadic usage)</p>
</li>
<li><p><code>MARKETING_TEST_XS</code> (barely used)</p>
</li>
</ul>
<p><strong>The Problem:</strong></p>
<p>Managing many separate warehouses leads to unnecessary costs due to idle compute time and minimum billing increments. Even quick 5-second queries incur charges for a full minute of compute. Across hundreds of warehouses, this adds up to significant wasted spend each month.</p>
<p><strong>The Adaptive Solution:</strong></p>
<p>With Adaptive Compute, the marketing team can convert each of their five warehouses to Adaptive, and still maintain the same warehouse names for accounting purposes. The shared compute pool ensures resources are available when needed without incurring idle time charges across five warehouses.</p>
<h1 id="heading-critical-unknowns-whats-still-unclear">Critical Unknowns: What's Still Unclear</h1>
<p>While Adaptive Compute offers clear operational benefits, it’s still in private preview and several important details remain unclear. And these details matter, especially for organizations under tight cost or performance SLAs.</p>
<h3 id="heading-limited-cost-control-mechanisms"><strong>Limited Cost Control Mechanisms</strong></h3>
<p>Adaptive Compute optimizes for performance and simplicity, not cost reduction. If Target Statement Size is deprecated as planned[<a class="post-section-overview" href="#references-section">1</a>], you'll have only one lever: the Warehouse Credit Limit. Without any settings to guide compute size per query, cost-saving strategies like pushing low-priority workloads to smaller compute are no longer possible.</p>
<p><strong>Consider this scenario:</strong> Your team runs a daily report that takes 2 minutes on Small compute (2 credits/hour = 0.067 credits) or 1.5 minutes on Medium compute (4 credits/hour = 0.10 credits).</p>
<p>With standard warehouses, your team can choose Small to save 33% on credits, but Adaptive Compute might decide on Medium due to the speed improvement, increasing your spend regardless of your priorities.</p>
<p><strong>What you lose:</strong></p>
<ul>
<li><p>Ability to force non-critical workloads onto smaller compute to save money (e.g., running non-critical reports on X-Small warehouses)</p>
</li>
<li><p>Option to set aggressive auto-suspend for development warehouses (e.g., setting 1-minute auto-suspend for ad-hoc warehouses)</p>
</li>
<li><p>Control over running specific workloads on larger warehouses when deadlines require it</p>
</li>
</ul>
<h3 id="heading-cache-behavior-uncertainty"><strong>Cache Behavior Uncertainty</strong></h3>
<p>Snowflake’s local disk cache can significantly boost query performance, with warm-cache queries often running 5–10x faster than cold ones. Standard warehouses with longer auto-suspend settings are more likely to retain this cache between queries. But with Adaptive's shared compute model, cache behavior becomes unpredictable, potentially impacting both performance and costs.</p>
<p><strong>Why this matters:</strong></p>
<ul>
<li><p>Dashboard queries that typically benefit from warm cache might see inconsistent performance</p>
</li>
<li><p>ETL pipelines that read the same base tables repeatedly could lose optimization opportunities</p>
</li>
<li><p>Cost implications if queries that previously hit cache now require full table scans</p>
</li>
</ul>
<h3 id="heading-monitoring-and-debugging-challenges">Monitoring and Debugging Challenges</h3>
<p>With standard warehouses, you can directly observe and control which warehouse a query runs on. With Adaptive Compute, the routing decisions happen behind the scenes, and it’s unclear what additional metadata Snowflake will surface around how those routing decisions are made, such as:</p>
<ul>
<li><p>What size compute ran each query and how routing logic behaved</p>
</li>
<li><p>Whether the router over‑ or under‑sized compute for specific queries</p>
</li>
<li><p>Whether queries are being queued due to credit limits or resource availability</p>
</li>
</ul>
<h3 id="heading-impact-on-spend"><strong>Impact on Spend</strong></h3>
<p>Snowflake's launch materials for Adaptive Compute emphasize ease of use and performance, with no mention of cost savings[<a class="post-section-overview" href="#references-section">2</a>, <a class="post-section-overview" href="#references-section">3</a>, <a class="post-section-overview" href="#references-section">4</a>]. This positioning suggests Adaptive Compute isn't designed to reduce spend, which is a critical consideration for organizations with FinOps accountability or tight budget constraints.</p>
<h1 id="heading-how-altimate-ais-auto-tune-delivers-control-and-automation">How Altimate AI's Auto Tune Delivers Control and Automation</h1>
<p>For organizations that want automation without sacrificing cost control, Altimate AI's Warehouse Auto Tune offers a powerful alternative. It brings intelligent optimization to your existing standard warehouses to optimize size, idle time, and cluster configuration while providing even finer-grained control over speed versus savings.</p>
<p><img src="/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/24663eaa-3c07-4d03-be84-ff45f81b1d95.png" alt class="image--center mx-auto" /></p>
<p><strong><em>Figure 3:</em></strong> <em>Daily cost breakdown showing Auto Tune savings over time. Each bar displays actual spend (yellow) and realized savings (green) from warehouse suspension, scaling, and sizing optimizations. On July 23, 2025, Auto Tune saved between $34.85 and $45.38, with most savings from Warehouse Suspension and Scaling. Total realized savings during the selected period exceeded $1.1K.</em></p>
<h3 id="heading-proactive-suspension-and-cluster-scaling"><strong>Proactive Suspension and Cluster Scaling</strong></h3>
<p>Auto Tune minimizes idle time by scaling back clusters and suspending warehouses before Snowflake's native auto-suspend triggers. It continuously monitors activity and proactively reduces compute allocation during quiet periods.</p>
<h3 id="heading-predictive-workload-based-resizing"><strong>Predictive Workload-Based Resizing</strong></h3>
<p>Auto Tune doesn't just react to current load – it predicts upcoming demand based on your historical workload patterns to determine when warehouses can be safely downsized without impacting performance.</p>
<p><strong>How it works in practice:</strong></p>
<p>Let's say you have a Large warehouse that processes heavy ETL jobs from 2-6 AM but runs mostly small queries the rest of the day. Auto Tune identifies this workload pattern and automatically:</p>
<ul>
<li><p>Maintains Large size during the 2-6 AM ETL window</p>
</li>
<li><p>Downsizes to Medium during low-demand periods</p>
</li>
<li><p>Returns to Large before the next ETL window</p>
</li>
</ul>
<h3 id="heading-granular-performance-safeguards"><strong>Granular Performance Safeguards</strong></h3>
<p>Auto Tune provides multiple mechanisms to protect critical workloads while optimizing costs:</p>
<p><strong>1. Custom Schedule Blocks</strong> Custom schedule blocks define specific time windows where warehouses must maintain a certain size. Examples:</p>
<ul>
<li><p>Weekdays 9-10 AM: Keep <code>EXECUTIVE_DASHBOARD_WH_XL</code> at default size X-Large for C-suite daily reviews to ensure performance</p>
</li>
<li><p>Sunday 2-5 AM: Keep <code>ARCHIVE_ETL_WH</code> downsized to Small while reprocessing past months of data to reduce costs</p>
</li>
</ul>
<p><strong>2. Real-Time Backoff Configuration</strong></p>
<p>Set performance thresholds that automatically reverse downsizing decisions if query latency or queue times exceed acceptable levels. When triggered, the system reverts to default size and pauses auto-resizing for one hour.</p>
<p><strong>Example Backoff Configurations for Different Workload Types:</strong></p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Workload Type</strong></td><td><strong>Latency Threshold</strong></td><td><strong>Queue Threshold</strong></td><td><strong>Rationale</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Customer-facing dashboards</td><td>120%</td><td>125%</td><td>Minimal tolerance for delays</td></tr>
<tr>
<td>Internal analytics</td><td>150%</td><td>150%</td><td>Balanced cost/performance</td></tr>
<tr>
<td>Batch ETL jobs</td><td>180%</td><td>170%</td><td>Cost savings prioritized</td></tr>
</tbody>
</table>
</div><h3 id="heading-transparency-and-control-over-decisions"><strong>Transparency and Control Over Decisions</strong></h3>
<p>Auto Tune provides full visibility into every optimization decision:</p>
<ul>
<li><p>Daily/weekly/monthly spend trends with savings clearly separated by agent</p>
</li>
<li><p>Detailed logs explaining why each resizing decision was made</p>
</li>
<li><p>Calendar view of all scheduled and completed optimization windows</p>
</li>
</ul>
<p><img src="/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/798f097c-7ae7-42aa-95c2-8b9d2a355511.png" alt class="image--center mx-auto" /></p>
<p><strong><em>Figure 4:</em></strong> <em>Auto Tune history log showing recent warehouse actions taken. The agents resized warehouses dynamically based on query patterns, including downsizing from Large to Medium size to reduce cost without impacting performance.</em></p>
<h3 id="heading-warehouse-eligibility-and-smart-targeting"><strong>Warehouse Eligibility and Smart Targeting</strong></h3>
<p>Auto Tune automatically evaluates each warehouse to determine if it's a good candidate for resizing optimization. Eligible warehouses typically have:</p>
<ul>
<li><p>Periods of low utilization with mainly small queries</p>
</li>
<li><p>Predictable daily or weekly patterns</p>
</li>
<li><p>Meaningful compute spend to optimize</p>
</li>
</ul>
<p>This ensures resizing agents only focus on warehouses where they can deliver real value and help cut costs.</p>
<h1 id="heading-making-the-right-choice-adaptive-vs-auto-tune">Making the Right Choice: Adaptive vs. Auto Tune</h1>
<p>Here are a few pointers for choosing the right solution.</p>
<h3 id="heading-choose-adaptive-compute-when"><strong>Choose Adaptive Compute When:</strong></h3>
<ul>
<li><p><strong>Simplicity is paramount:</strong> You want to eliminate warehouse management entirely</p>
</li>
<li><p><strong>Workloads are unpredictable:</strong> Highly variable query patterns make sizing difficult</p>
</li>
<li><p><strong>Performance matters most:</strong> You're willing to pay more for consistent speed</p>
</li>
<li><p><strong>You're consolidating many underutilized warehouses:</strong> The reduction in idle time offsets other costs</p>
</li>
</ul>
<h3 id="heading-choose-auto-tune-when"><strong>Choose Auto Tune When:</strong></h3>
<ul>
<li><p><strong>Cost control is critical:</strong> You have specific spending targets to hit</p>
</li>
<li><p><strong>Workloads follow patterns:</strong> Your queries have predictable daily/weekly cycles</p>
</li>
<li><p><strong>You need granular control:</strong> Different workloads require different cost/performance tradeoffs</p>
</li>
<li><p><strong>You want transparency:</strong> Detailed visibility into optimization decisions and savings</p>
</li>
</ul>
<h3 id="heading-hybrid-approach"><strong>Hybrid Approach</strong></h3>
<p><strong>Many organizations will benefit from using both solutions strategically.</strong> For example:</p>
<ul>
<li><p>Convert your <code>DATA_SCIENCE_SANDBOX</code> warehouse to Adaptive Compute since data scientists run unpredictable queries at random times</p>
</li>
<li><p>Keep your <code>PRODUCTION_ETL</code> warehouse on standard with Auto Tune, reducing spend through predictable downsizing during known quiet periods</p>
</li>
<li><p>Use Adaptive for all development/test warehouses to eliminate idle charges</p>
</li>
<li><p>Apply Auto Tune to customer-facing warehouses where you need cost control with performance guarantees</p>
</li>
</ul>
<h1 id="heading-final-thoughts">Final Thoughts</h1>
<p>Snowflake's Adaptive Compute and Altimate AI's Auto Tune represent two philosophies for warehouse optimization: total simplicity versus intelligent control. Adaptive Compute eliminates management overhead but sacrifices cost optimization levers. Auto Tune maintains the flexibility of standard warehouses while adding automation that typically reduces costs by 10-20%.</p>
<p>Start by analyzing your warehouse utilization patterns and cost targets. If predictable savings matter more than operational simplicity, Auto Tune is likely your best choice. If you're drowning in warehouse management complexity and can accept higher costs for simplicity, Adaptive Compute offers compelling benefits. For most organizations, a hybrid approach will deliver the best of both worlds.</p>
<p>If your team already has tools in place for analyzing warehouse usage patterns, monitoring cost targets, and automating warehouse optimization, you're all set. If not, we can help you with the analysis, optimization, and choosing between Adaptive and standard warehouses based on your needs. <a target="_blank" href="https://app.myaltimate.com/contactus">Reach out to us</a> for a no-cost POC.</p>
<p><a id="references-section"></a></p>
<h1 id="heading-references">References</h1>
<ol>
<li><p><a target="_blank" href="https://reg.snowflake.com/flow/snowflake/summit25/sessions/page/catalog/session/1741712659023001GszH">What's New: Faster Insights with Snowflake Standard Warehouse - Gen2 and Adaptive Compute</a>. Snowflake Summit 2025 Session Catalog. June 3, 2025.</p>
</li>
<li><p><a target="_blank" href="https://www.snowflake.com/en/news/press-releases/snowflake-unveils-next-wave-of-compute-innovations-for-faster-more-efficient-warehouses-and-ai-driven-data-governance/">Snowflake Unveils Next Wave of Compute Innovations For Faster, More Efficient Warehouses and AI-Driven Data Governance</a>. Snowflake press release, June 3, 2025.</p>
</li>
<li><p><a target="_blank" href="https://www.snowflake.com/en/blog/adaptive-compute-smarter-warehouses/">Introducing Even Easier-to-Use Snowflake Adaptive Compute with Better Price/Performance</a>. Snowflake Blog, June 3, 2025.</p>
</li>
<li><p><a target="_blank" href="https://medium.com/snowflake/how-snowflakes-adaptive-warehouse-is-revolutionizing-data-operations-at-pfizer-f90f1730ef0c">How Snowflake’s Adaptive Warehouse Is Revolutionizing Data Operations at Pfizer</a>. Snowflake Builders Blog on Medium; Matt Massey, June 3, 2025.</p>
</li>
</ol>
<hr />
<p>Deliver more performance and cost savings with Altimate AI's cutting-edge AI teammates. These intelligent teammates come pre-loaded with the insights discussed in this article, enabling you to implement our recommendations across warehouses, tables, and millions of queries effortlessly. Ready to see it in action? Request a recorded demo by <a target="_blank" href="https://app.myaltimate.com/contactus">sending us a chat message</a>) and discover how AI teammates can transform your data teams.</p>
<p><a target="_blank" href="https://app.myaltimate.com/contactus"><img src="/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/d9ad5daf-6edc-4c94-a697-80f6cb79cbc5.png" alt /></a></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses/6da7cca8-4c24-457a-80da-e02f4eb8bff6.jpeg" type="image/jpeg" />
  </item>
  <item>
    <title>Supercharging Cursor IDE: How the dbt Power User Extension’s Embedded MCP Server Unlocks AI-Driven dbt Development</title>
    <link>https://altimate.ai/blog/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development</link>
    <guid isPermaLink="true">https://altimate.ai/blog/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development</guid>
    <pubDate>Fri, 21 Mar 2025 02:51:16 GMT</pubDate>
    <dc:creator>Anand Gupta</dc:creator>
    <category>cursor ai</category>
    <category>dbt</category>
    <category>data-engineering</category>
    <category>altimateAI</category>
    <category>#ai-tools</category>
    <category>AI</category>
    <description>Introduction
We’re excited to announce a major new capability in the dbt Power User VSCode extension: an embedded Model Context Protocol (MCP) server. This MCP server is now built directly into the extension, acting as a bridge between AI-powered dev...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development/49891252-c36a-48cc-9e28-589ba5ea1d33.jpeg" alt="Supercharging Cursor IDE: How the dbt Power User Extension’s Embedded MCP Server Unlocks AI-Driven dbt Development" /></p>
<h2 id="heading-introduction">Introduction</h2>
<p>We’re excited to announce a major new capability in the <strong>dbt Power User</strong> VSCode extension: an embedded <strong>Model Context Protocol (MCP)</strong> server. This MCP server is now built directly into the extension, acting as a bridge between AI-powered development tools and your dbt project. The motivation behind implementing an embedded MCP server is to enable seamless communication between AI assistants (like those in Cursor IDE) and dbt, eliminating the friction of context switching. In practical terms, this means your AI coding assistant can query your dbt project’s schema, compile models, run tests, and more – all through a standardized protocol – leading to faster development workflows and greater efficiency for dbt developers.</p>
<p>By leveraging the MCP server, dbt Power User can expose rich project context and operations to AI agents in real-time. This empowers data engineers to automate repetitive tasks (like looking up column definitions or running model builds) and accelerates development. The embedded MCP server unlocks new AI-driven workflows for dbt, from intelligent autocompletion to on-demand documentation generation, all while keeping the interaction localized and secure within your development environment.</p>
<h2 id="heading-technical-architecture-and-cursor-ide-integration">Technical Architecture and Cursor IDE Integration</h2>
<p>At a high level, the MCP server runs as a lightweight web service within the dbt Power User extension environment. The server spins up automatically when you open a dbt project (if you have enabled the MCP feature) and listens on a local port. It selects an available port dynamically at launch to avoid conflicts, and registers itself with Cursor by updating Cursor’s MCP configuration. Once running, the Cursor IDE detects the MCP server and establishes a connection so its AI assistant can invoke dbt-related “tools” exposed by the server.</p>
<p><img src="/blog/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development/64322c3e-e90b-4fff-810e-ea4e6a17b8b1.png" alt class="image--center mx-auto" /></p>
<p><strong>Server Components and Design:</strong> The MCP server architecture is composed of a few key components working in tandem:</p>
<ul>
<li><p><strong>Server Core:</strong> the core HTTP server (built with the MCP SDK) that handles incoming requests and responses. It defines the MCP endpoints and protocol handling (e.g. registering available tools, managing sessions, etc.). The server core orchestrates requests from Cursor’s AI and ensures each is routed to the appropriate handler in the extension.</p>
</li>
<li><p><strong>Tool Registry:</strong> a registry of <strong>tools</strong> – individual operations or actions related to dbt. Each tool has a name and a function implementing its behavior. When the server starts, it registers a suite of tools (detailed in the next section) that allow the AI to perform various dbt tasks. The Tool Registry essentially maps MCP requests to the extension’s internal methods or dbt CLI calls. It also defines metadata for each tool (like input parameters and descriptions) that Cursor’s AI can utilize to formulate requests.</p>
</li>
<li><p><strong>SSE Transport:</strong> the server uses <strong>Server-Sent Events (SSE)</strong> for real-time communication back to the client. After Cursor connects to the MCP server, it maintains an open SSE channel. When a tool is executed, results (and any interim output or logs) are sent as a stream of events over this channel to Cursor. This means the AI can receive data or status updates from long-running tasks in real time, without polling. For example, if you execute a model run via the AI, the MCP server can stream back logs or a success/failure message as soon as it’s available. Using SSE for output ensures a responsive, event-driven interaction between the extension and the AI assistant.</p>
</li>
</ul>
<p><img src="/blog/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development/21274320-18a7-4b37-9fb5-02818ed815de.png" alt class="image--center mx-auto" /></p>
<p><em>Architecture of the MCP Server integration with Cursor.</em></p>
<p><strong><em>The diagram shows the Cursor IDE’s AI assistant interacting with the MCP server via tool requests.</em></strong> <em>The MCP server (within the dbt Power User extension) processes these requests using its registered tools. It interacts with in-memory dbt project artifacts for quick context and, when needed, invokes the dbt Integration module (which in turn may query the data warehouse) to fulfill the request. Results and logs are returned back to the AI client in real-time via SSE.</em></p>
<p><strong>Communication Flow:</strong> The end-to-end flow of a typical interaction involves several steps that connect the AI to your dbt project:</p>
<ol>
<li><p><strong>AI Initiates a Tool Request:</strong> Within Cursor, the AI assistant decides to call a tool (for example, “get the SQL definition of model X” or “run tests for model Y”) and sends a request through the MCP protocol.</p>
</li>
<li><p><strong>MCP Server Receives the Request:</strong> The server core matches the incoming request to one of the registered tools in its registry and hands off execution to that tool’s handler.</p>
</li>
<li><p><strong>Tool Execution:</strong> The tool’s handler runs inside the extension process. It may fetch information from the in-memory dbt artifacts (e.g. to get a model’s definition or lineage) or execute a dbt operation. The handler leverages the extension’s existing capabilities – for example, calling a function in the extension that wraps dbt operations to perform the task.</p>
</li>
<li><p><strong>In-Memory Artifact Access:</strong> If the tool needs to read project structure (models, sources, tests, etc.), it queries the up-to-date in-memory representation of the dbt project (more on this in the next section). This avoids expensive disk or CLI operations for retrieving metadata. If the tool needs to run SQL or dbt operations, it might invoke the dbt integration module and use the database connections configured in the dbt profile.</p>
</li>
</ol>
<p>In essence, the MCP server turns the dbt extension into a real-time API for your dbt project. Cursor’s AI no longer operates in a vacuum – it can actively query your project’s state and perform operations, treating the dbt project as an interactive context it can reason about. All of this happens locally within your development environment, leveraging the work the extension is already doing to maintain dbt context.</p>
<h2 id="heading-in-memory-dbt-artifacts-lifecycle-and-performance-optimization">In-Memory dbt Artifacts Lifecycle and Performance Optimization</h2>
<p>One of the standout benefits of the MCP server is that it can serve data to the AI assistant <strong>directly from memory</strong>, without constantly hitting your filesystem or database. The dbt Power User extension maintains an in-memory representation of your project’s artifacts as you work. This includes the parsed project manifest (models, sources, tests, exposures, etc. along with their relationships), and metadata like the active target and project name. By tapping into these in-memory artifacts, the MCP server can answer many questions instantly and run operations more efficiently.</p>
<p><strong>Creation and Initialization:</strong> When you open a dbt project in VS Code, the extension immediately initializes and parses the project. It loads manifest information (by invoking dbt’s parse operation under the hood and translating it to its own in-memory representation through its own parser) to build a graph of models and references in memory. This means the extension knows about all your model definitions, sources, tests, and their lineage as soon as the project is ready. At the moment the MCP server starts (which typically coincides with project load or when you enable the feature), it attaches to this ready-to-use project context. The server core may wait until the dbt project is fully initialized and then mark its tools as available for the AI. Essentially, <strong>the server boots up after the dbt context is prepared</strong>, ensuring the AI always sees a consistent project state.</p>
<p><strong>Live Updates:</strong> As you modify files or the project state changes, the in-memory artifacts are updated incrementally. The extension listens to file system events and dbt execution outcomes – for example, if you edit a model file, it can re-parse that model and update the manifest graph in memory. Likewise, running <code>dbt deps</code> will refresh the list of installed packages in memory. The MCP server subscribes to these internal events. If the manifest is updated or a new run is completed, the server can invalidate or refresh relevant cached data. This way, tools like “get children models of X” will always use the latest information. The lifecycle is managed such that <strong>any time the dbt project changes, the in-memory state and the MCP server’s view of it remain in sync</strong>. This is much faster than re-running <code>dbt</code> commands for each query and ensures the AI doesn’t get stale data.</p>
<p><strong>Efficient Querying:</strong> Because the data is in memory, tools that retrieve info (e.g. listing models, showing a model’s SQL, computing lineage) execute extremely quickly. There’s no need to spawn a subprocess or read from disk for these – the extension can simply look up the Python/TypeScript object representing that model. Even complex lineage traversals or dependency graphs can be resolved by the extension’s code using pre-computed relationships. This optimization is critical for performance: it allows the AI to ask a series of detailed questions about your project without incurring heavy overhead. For example, an AI reasoning about why a model’s test failed can rapidly pull the model’s SQL, its parent models, and the test definition via multiple MCP tool calls in seconds, whereas doing this via CLI repeatedly would be far slower.</p>
<p><strong>Cleanup and Lifecycle End:</strong> The MCP server’s lifetime is tied to your VS Code session and project. If you close the project or disable the extension, the server is stopped and the in-memory artifacts are freed. The implementation ensures that sockets are closed and event listeners are disposed to avoid resource leaks. Notably, the server core exposes a clean <strong>dispose()</strong> method that the extension calls on shutdown, which shuts down the SSE stream and prevents further tool calls.</p>
<p>Overall, the approach of leveraging in-memory artifacts means that the MCP server can provide a <strong>fast, rich context</strong> to the AI. It capitalizes on the work already being done by the dbt Power User extension’s internal DBT parser and project tracker. This not only speeds up AI interactions but also avoids unnecessary load on your data warehouse – the AI can get a lot of information without executing a single query, unless absolutely necessary for the task.</p>
<h2 id="heading-capabilities-unlocked-tools-provided-by-the-mcp-server">Capabilities Unlocked: Tools Provided by the MCP Server</h2>
<p>The MCP server exposes a robust set of tools that the AI assistant can use. These tools cover most day-to-day dbt tasks and are grouped into a few categories for clarity. Below is a breakdown of major capabilities and examples of tools in each category:</p>
<h3 id="heading-project-amp-environment-management-tools">Project &amp; Environment Management Tools</h3>
<ul>
<li><strong>Project Information:</strong> Usually the AI will fetch all the dbt projects and its roots first, to know on which project it should work. The AI will use the root of the project as a parameter to the other tools. For instance, a tool <code>GET_PROJECT_NAME</code> returns the dbt project name for the given root, and <code>GET_SELECTED_TARGET</code> returns which target/profile is active. This is useful for the AI to contextually understand which environment it’s working with (production or development).</li>
</ul>
<h3 id="heading-model-and-source-exploration-tools">Model and Source Exploration Tools</h3>
<ul>
<li><p><strong>Model SQL and Schema:</strong> Tools in this category allow the AI to fetch the content or properties of dbt models and sources. For example, a <code>COMPILE_QUERY</code> tool can return the raw SQL of a model file, and a <code>GET_COLUMNS_OF_SOURCE</code> could return details about a source (like database/schema and columns as defined in YAML). With these, the AI can, say, read the logic of a model to help debug or suggest changes.</p>
</li>
<li><p><strong>Lineage and Dependency Queries:</strong> We provide tools like <code>GET_CHILDREN_MODELS</code> and <code>GET_PARENT_MODELS</code>, which return the immediate downstream and upstream models of a given model. The AI can use these to understand the dependency graph – for instance, finding what will be impacted if a model is changed or which upstream data sources feed into it. Internally, these tools leverage the manifest graph in memory to quickly compute the relationships. Additionally, there are count-based queries (like a tool to count the number of models depending on a source) to aid impact analysis.</p>
</li>
<li><p><strong>Column Lineage and Documentation:</strong> (Upcoming) The extension already has features for column-level lineage and documentation. Through MCP, we intend to expose tools so the AI can answer questions like “which models use column X from source Y” or even retrieve documentation strings for a model or column. This will bridge the gap between documentation and code by letting the AI pull in documented context as needed.</p>
</li>
</ul>
<h3 id="heading-sql-compilation-amp-execution-tools">SQL Compilation &amp; Execution Tools</h3>
<ul>
<li><p><strong>Compile SQL:</strong> The AI might want to see how dbt renders a model’s SQL with Jinja templating. The <code>COMPILE_QUERY</code> tool takes a query (and optionally the model it is derived from) and returns the compiled SQL, exactly as dbt would generate it. This is extremely useful for checking logic or debugging macros – the AI can get the SQL that would run on the warehouse, without actually running it. It uses dbt’s compilation engine (via the extension’s interface to dbt Core) under the hood.</p>
</li>
<li><p><strong>Execute Arbitrary SQL:</strong> Sometimes the AI will need to run a query to answer a question (for example, “preview the first 10 rows of model X”). The <code>EXECUTE_SQL</code> tool (with a configurable row limit) allows running a SQL query against the project’s data warehouse connection and returns results, ensuring we don’t pull massive datasets by accident. The AI could use this to validate assumptions or provide sample data to the user. Users must explicitly permit this feature, as executing SQL will share data with the AI.</p>
</li>
<li><p><strong>Run dbt Models:</strong> For full pipeline execution, we offer tools to run or build models. The <code>RUN_MODEL</code> tool triggers <code>dbt run</code> for a specific model (and optionally its dependencies), while <code>BUILD_MODEL</code> can run the model and its tests (equivalent to <code>dbt build</code> for that model). There’s also a <code>BUILD_PROJECT</code> for running the entire project (<code>dbt build</code>). These commands execute in the background through the extension’s job runner. The AI can thus initiate a model run or a full project build from within the conversation – for example, “Re-run the revenue model to see if the issue is fixed.”</p>
</li>
</ul>
<h3 id="heading-testing-and-validation-tools">Testing and Validation Tools</h3>
<ul>
<li><p><strong>Execute Tests:</strong> The server provides a <code>RUN_TEST</code> tool to execute a specific dbt test by name, as well as <code>RUN_MODEL_TEST</code> to run all tests associated with a particular model. This allows the AI to verify data quality or detect if recent changes broke any tests. For instance, after modifying a model, the AI might call <code>RUN_MODEL_TEST</code> to ensure all tests still pass and then report the results. Test results or failures will be returned via the event stream.</p>
</li>
<li><p><strong>SQL Validation:</strong> (Planned) Even without running on the warehouse, the extension can do a lightweight SQL parse/validation. A tool is available to validate a SQL query (checking for syntax errors, missing refs, etc.) without executing it. This is similar to the extension’s existing <strong>SQL Lint</strong> feature, now accessible to the AI. It can prevent the AI from running a bad query by first validating it and catching errors.</p>
</li>
<li><p><strong>Performance Analysis:</strong> (Planned) We aim to add tools that use dbt’s compilation stats or query planner insights to help the AI assist in performance tuning. For example, a tool to show the <strong>compiled query explain plan</strong> (if the warehouse supports <code>EXPLAIN</code>) or to estimate the cost of a query. Such tools would let the AI caution the user if a query might be expensive or if a model lacks proper pruning filters, etc.</p>
</li>
</ul>
<h3 id="heading-package-management-and-repository-tools">Package Management and Repository Tools</h3>
<ul>
<li><p><strong>Install Packages:</strong> Managing dbt packages is made easier with tools like <code>INSTALL_DEPS</code> which runs <code>dbt deps</code> to install the packages listed in <code>packages.yml</code>. There’s also an <code>ADD_DBT_PACKAGES</code> tool that can add new packages on the fly. For example, if the AI suggests using a package (like dbt-utils), it could call <code>ADD_DBT_PACKAGES</code> with the package name and version – the extension will add it to <code>packages.yml</code> and run <code>dbt deps</code> internally to install it, returning the result. This showcases agentic behavior: the AI can not only suggest but also take action to modify your project structure (with your permission).</p>
</li>
<li><p><strong>Upgrade dbt Version:</strong> Although not explicitly a tool in this release, the infrastructure could allow the AI to assist in upgrading the dbt version or dependencies. For example, by reading <code>requirements.txt</code> or checking the installed dbt version, and then running pip installs. This would likely be added as a safe tool in future once we ensure such actions are gated behind user approval.</p>
</li>
<li><p><strong>Git Operations:</strong> While primarily focused on dbt tasks, the larger vision includes enabling some project-level Git interactions via MCP (for example, checking out a new branch for a fix, or opening a pull request). The current server does not directly include Git tools, but it lays the groundwork for integrating such capabilities alongside dbt tasks, so the AI could orchestrate end-to-end workflows (code change -&gt; run model -&gt; test -&gt; commit).</p>
</li>
</ul>
<p>All these tools are defined in the extension and registered with the MCP server at startup. When Cursor’s AI is formulating a plan to help you, it queries the MCP server for an index of available tools (the MCP protocol allows the client to discover tools and their input schema). The AI sees something like “I have a tool called <code>get_children_models</code> that needs a <code>table</code> name” and it can then decide to use it if the user asks a question about model dependencies.</p>
<h2 id="heading-under-the-hood-port-management-error-handling-and-security">Under the Hood: Port Management, Error Handling, and Security</h2>
<p>Building an embedded server inside an IDE extension comes with its own engineering challenges. We put significant effort into making sure the MCP server runs smoothly without disrupting your workflow.</p>
<p><strong>Port Management:</strong> Since the MCP server is local, it needs to choose a port to listen on. We default to letting the OS assign an open port (by binding to port 0, which yields an ephemeral port). Once the server is listening, the extension logs the chosen port. If for some reason the port is not reachable or Cursor cannot connect, the extension will surface an error message. We also handle the case where the server might need to restart (for example, if you re-initialize the project) by cleaning up the old server and starting a new one potentially on a new port. The extension ensures there is only one MCP server instance per workspace to avoid port conflicts. In the future, we may allow a fixed port configuration if users want to expose the server to other tools, but in this beta it’s fully managed and isolated.</p>
<p><strong>Error Handling and Resilience:</strong> The MCP server includes robust error handling so that failures in tools do not crash the server or hang the AI. Each tool execution is wrapped in try/catch logic. If a tool throws an exception (say, dbt fails to compile a query due to a syntax error), the error is caught and sent back as an error event to the AI, and the server remains up for subsequent requests. We’ve instrumented comprehensive logging via the extension’s output channel (the “dbt Power User” output panel in VS Code) to record any exceptions or problematic requests. This makes it easier to debug if something goes wrong – both for us as developers and for users who can check the logs. Overall, the server is designed to be <strong>long-running and robust</strong>, recovering gracefully from errors. In our tests, issues like missing profiles or syntax errors are caught and reported back to the AI without terminating the server.</p>
<p><strong>Security Measures:</strong> Since the MCP server allows automated actions on your project, we have restricted its accessibility to ensure safety. The server <strong>binds only to localhost</strong> and is not accessible from external machines. This means only processes on your computer (like the Cursor IDE) can communicate with it, mitigating risk of any outside interference. Additionally, the server enforces that requests conform to the expected MCP schema – it will reject any malformed requests or unknown tool calls rather than executing them arbitrarily. We also incorporated a simple authentication check in this beta: the MCP server feature will only start if certain preconditions are met (for instance, verifying that you have a valid Altimate API key configured, which is used to enable AI features in the extension). This is mainly to gate the feature during beta and ensure usage can be monitored and supported. In the future, we plan to add more sophisticated security, such as an authentication token for the MCP connection or user consent prompts in VS Code before executing potentially destructive actions (like modifying files or running DDL statements). It’s important to note that the AI agent in Cursor will only use tools in ways you allow – you’re always in control and can disable or limit certain tools if desired. We recommend keeping the extension and Cursor up-to-date to get the latest security improvements. As the community and usage of MCP servers grow, we’ll continue to harden the server (for example, adding rate limiting or sandboxing if the scenario requires it).</p>
<p><strong>Resource Usage:</strong> Running an MCP server is lightweight. It piggybacks on the extension’s process and uses minimal additional memory (mostly just for the HTTP server overhead). The in-memory artifact store is already in place for the extension’s normal operation. We’ve observed negligible impact on VS Code’s performance when the server is idle. During heavy use (like a lot of model runs triggered by AI), there is some CPU and memory use, but it’s equivalent to you running those dbt commands manually. When idle, the server simply holds open a socket for Cursor. If needed, you can always stop the server by disabling the feature in settings, which immediately frees the port and associated resources.</p>
<p><strong>Future Enhancements:</strong> In upcoming releases, we plan to enhance both the capabilities and the internals of the MCP server. On the capability side, we’re looking at adding more tools (as mentioned, possibly Git operations, documentation queries, etc.) and integrating deeper with other systems (imagine the AI triggering an Airflow DAG after a successful dbt run, via a future Airflow MCP server). We’re also considering a plugin mechanism where users could write custom MCP tools for their own macros or operations and have the server load them. Finally, as the MCP protocol evolves (it’s an open standard in active development), we will adapt our server to remain compliant and take advantage of new features. For example, Anthropic’s Claude models recently embraced MCP natively, and we expect more LLMs to follow – our goal is to have the dbt MCP server work with any AI agent that speaks MCP, not just Cursor’s.</p>
<h2 id="heading-conclusion-our-vision-toward-an-ai-integrated-data-platform">Conclusion: Our Vision Toward an AI-Integrated Data Platform</h2>
<p>The introduction of the MCP server in the dbt Power User extension is a significant step toward an <strong>AI-integrated data development platform</strong>. We’ve turned the VS Code + dbt environment into an AI-accessible service, enabling smarter assistance and automation. This capability is not an isolated feature – it’s part of our broader vision to integrate AI with all facets of the modern data stack. In the near future, you can expect similar integrations with <strong>Snowflake and Postgres</strong> (for example, an AI agent that can profile or manipulate your warehouse data), with <strong>Airflow</strong> (an AI that can inspect DAGs or trigger workflows), and more. Our <strong>DataPilot platform</strong> is evolving into an ecosystem of AI “teammates” that collaborate across tools. The dbt MCP server is one of these teammates, focused on analytics engineering, and it will collaborate with others (imagine an AI assistant that understands your data warehouse, your pipelines, and your dbt models collectively).</p>
<p>We invite you to try out the MCP server. Since it’s a beta release, we greatly value your feedback. Join our community Slack channel (<a target="_blank" href="https://getdbt.slack.com/archives/C05KPDGRMDW"><code>#tools-dbt-power-user</code></a> on dbt Slack) to share your experiences or ask any questions. . If you need help setting it up or want to explore how this could fit into your team’s workflow, please <a target="_blank" href="https://app.myaltimate.com/contactus"><strong>reach out to us</strong></a> . We’re also eager to collaborate with teams interested in pushing the boundaries of AI in data engineering. Whether you have ideas for new MCP tools or want to integrate our platform with your own, let’s start a conversation. Together, let’s redefine what a “power user” can do by combining the strengths of dbt with the intelligence of AI. This launch is just the beginning, and we’re excited to build a more connected, intelligent data platform with your input.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development/49891252-c36a-48cc-9e28-589ba5ea1d33.jpeg" type="image/jpeg" />
  </item>
  <item>
    <title>Could AI Teammates Be the Secret to Efficient Snowflake Cost Management?</title>
    <link>https://altimate.ai/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management</link>
    <guid isPermaLink="true">https://altimate.ai/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management</guid>
    <pubDate>Wed, 13 Nov 2024 15:21:53 GMT</pubDate>
    <dc:creator>John Ryan</dc:creator>
    <category>snowflake administration</category>
    <category>agentic AI</category>
    <category>Artificial Intelligence</category>
    <category>snowflake</category>
    <category>Snowflake performance</category>
    <category>ai-teammates</category>
    <description>In the past five years, Snowflake has disrupted the database, data storage, and analytics industry by massively simplifying the entire data and analytics landscape. However, a new wave of innovation is horizon - Artificial Intelligence and AI Teammat...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/4f08497b-47c6-43da-96bc-8a3047f5b8fe.jpeg" alt="Could AI Teammates Be the Secret to Efficient Snowflake Cost Management?" /></p>
<p>In the past five years, Snowflake has disrupted the database, data storage, and analytics industry by massively simplifying the entire data and analytics landscape. However, a new wave of innovation is horizon - Artificial Intelligence and AI Teammates.</p>
<p>This article won't discuss <a target="_blank" href="https://research.ibm.com/blog/what-is-generative-AI">Generative AI</a>, which is (shockingly) already old news, but how AI Teammates working with AI Agents can collaborate alongside your (human) Snowflake System Administrator to help maximize performance and optimize spending on your Snowflake system.</p>
<p>After reading this article, you’ll realize just how powerful this technology is and what a potentially massive game-changer it presents.</p>
<h2 id="heading-what-is-an-agentic-ai">What is an Agentic AI?</h2>
<p>Unless you've been living under a rock for the past two years, you'll be well acquainted with <a target="_blank" href="https://chatgpt.com/">Chat-GPT</a> (other <a target="_blank" href="https://bestarion.com/generative-ai-chatbots/#:~:text=Jasper%20AI,of%20text%20quickly%20and%20efficiently.">AI Chatbots</a> are available), but these are simply passive assistants that quietly wait for your questions and generate text.</p>
<p>That's not denigrate the impact of <a target="_blank" href="https://www.snowflake.com/resource/generative-ai-and-llms-for-dummies/?utm_source=google&amp;utm_medium=paidsearch&amp;utm_campaign=em-gb-en-nb-genaillm-exact&amp;utm_content=go-rsa-evg-eb-generative-ai-and-llms-for-dummies&amp;utm_term=c-g-large%20language%20model-e-690007389282&amp;gad_source=1&amp;gbraid=0AAAAADCzRJUdbdjyUGTGfqHV7XQ5NYv_t&amp;gclid=EAIaIQobChMI4LfK1tGSiQMVEYuDBx0LvAnxEAAYAyAAEgKlXvD_BwE">Large Language Models</a> (LLMs), as a recent <a target="_blank" href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/the-economic-potential-of-generative-ai-the-next-productivity-frontier#key-insights">McKinsey Report</a> indicates that generative AI will add up to $4 trillion to the global economy with up to 70% less employee work required. Indeed, Artificial Intelligence is well on the way to being integrated into almost <a target="_blank" href="https://hogonext.com/how-to-apply-ai-effectively-for-data-warehousing/">every aspect</a> of Data Warehousing.</p>
<p>However, unlike Chat GPT that passively waits for user requests, an AI Teammate works alongside existing staff to monitor query patterns, identify potential issues and offer actionable tuning suggestions. They act as an artificially intelligent advisor, perhaps using machine learning to refine recommendations based on administrator feedback.</p>
<p>AI teammates work autonomously to recommend real-time system configuration and processing adjustments, reacting to events and recommending remedial actions to improve Snowflake customer experience or optimize cost.</p>
<p>Whereas an AI Teammate provides a consulting role, communicating with System Admins in natural language, <a target="_blank" href="https://www.ibm.com/think/topics/ai-agents">AI Agents</a> work autonomously to handle the low-level monitoring, analyzing query patterns and resource usage. In many ways, AI Agents are the back-room workers, providing data to be analyzed and interpreted by the AI Teammates which in turn support the Snowflake Admins.</p>
<p>Taken together, these are often referred to as <a target="_blank" href="https://aisera.com/blog/agentic-ai/#:~:text=Agentic%20AI%20uses%20reinforcement%20learning,reactive%20approach%20of%20Gen%20AI.">Agentic AI</a>.</p>
<h2 id="heading-key-features-of-ai-teammates-and-agentic-ai">Key Features of “AI Teammates” and “Agentic AI”</h2>
<p>It's all well and good using jargon like “AI Agents” - but what makes a solution “<a target="_blank" href="https://www.ssonetwork.com/intelligent-automation/articles/what-is-agentic-ai#:~:text=Agentic%20AI%20refers%20to%20a,without%20requiring%20direct%20human%20intervention.">Agentic</a>” as opposed to, (for example), a Python script that uses machine learning to identify and alert users of potential problems.</p>
<p>Here's a list of the key features an “<a target="_blank" href="https://www.ssonetwork.com/intelligent-automation/articles/what-is-agentic-ai#:~:text=Agentic%20AI%20refers%20to%20a,without%20requiring%20direct%20human%20intervention.">Agentic AI</a>” system.</p>
<ul>
<li><p><strong>Dynamic Problem Solving</strong>: Instead of relying on fixed scripts, in exactly the same way Chat-GPT can currently generate and execute python code, AI agents will generate source code and scripts to analyze data and solve problems . AI Teammates work just like a real person — assessing the situation, deciding what needs to be done, and then executing the plan.</p>
</li>
<li><p><strong>Reduced Technical Skills</strong>: IT automation typically needs technical experts (DBAs and System Admins) to configure and maintain it through scripting. In contrast, Agentic AI allows anyone, including non-coders, to instruct the system in natural language. For example, a user could give the AI an objective like “reduce warehouse costs by reducing idle time” and the AI would figure out the best way to do that, without needing predefined scripting.</p>
</li>
<li><p><strong>Autonomous Operation</strong>: Agentic AI doesn’t need constant supervision. Once given a goal, it will continuously monitor for opportunities to act and take the next steps without waiting for further instructions.</p>
</li>
<li><p><strong>Real-World Interaction</strong>: These AI systems will connect with external tools and databases, pulling in real-time information, and even executing actions like sending emails or making configuration changes. For example, an AI Teammate tasked with reducing Snowflake Virtual Warehouse costs could automatically resize warehouses in real-time to maintain a balance between cost and performance.</p>
</li>
<li><p><strong>Efficiency &amp; Adaptability</strong>: These systems can handle complex workflows by breaking down tasks into smaller steps, calling different tools, and even calling upon AI Agents to handle specific tasks. As AI Teammates are largely autonomous, they are highly efficient needing little human interaction and constantly adapt to changing circumstances.</p>
</li>
</ul>
<h2 id="heading-how-can-ai-teammates-work-on-snowflake">How can AI Teammates work on Snowflake?</h2>
<p>AI Teammates can play a vital role in optimizing a complex Snowflake Data Warehouse deployment by automating performance tuning tasks. Here are some practical examples of how Agentic AI could be deployed:</p>
<h3 id="heading-tuning-query-performance"><strong>Tuning Query Performance</strong></h3>
<ul>
<li><p><strong>Identifying Slow Queries</strong>: An AI Teammate could continuously monitor query elapsed times against an objective, prioritizing performance over cost. It would then suggest optimizations, such as <a target="_blank" href="https://articles.analytics.today/snowflake-cluster-keys-and-micro-partition-elimination-best-practices">improving partition pruning</a> or moving a given workload to a different <a target="_blank" href="https://blog.altimate.ai/does-size-matter-what-else-is-important-in-choosing-a-snowflake-warehouse">warehouse size</a>.</p>
</li>
<li><p><strong>Query Rewriting</strong>: If a query can be rewritten for better performance (e.g., using specific functions like LIMIT to <a target="_blank" href="https://articles.analytics.today/boost-your-snowflake-query-performance-with-these-10-tips">reduce data scanning</a>), the AI Teammate could automatically suggest or implement these changes after analyzing the query execution plan. Of course, this may need a “human in the loop” to verify, test, and deploy the changed code.</p>
</li>
</ul>
<h3 id="heading-virtual-warehouse-management"><strong>Virtual Warehouse Management</strong></h3>
<p>The screenshot below illustrates how AI Agents deployed by Altimate.AI automatically monitor and tune system configuration to identify potential cost savings and implement configuration changes to eliminate waste.</p>
<p><a target="_blank" href="https://www.altimate.ai/"><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/ea54c3af-410a-45a2-979f-fbd7914bd3ae.png" alt class="image--center mx-auto" /></a></p>
<ul>
<li><p><strong>Warehouse Configuration</strong>: AI Teammates can continuously monitor <a target="_blank" href="https://articles.analytics.today/snowflake-virtual-warehouses-what-you-need-to-know">virtual warehouse</a> usage patterns and (for example), automatically adjust the AUTO_SUSPEND, WAREHOUSE SIZE or CLUSTER COUNT settings to optimize efficiency. For instance, if a warehouse remains idle longer than expected, the AI Teammate could reduce the auto-suspend timeout or automatically resize warehouses during off-peak hours to reduce costs.</p>
</li>
<li><p><strong>New Feature deployment:</strong> Agentic AI could automatically detect and recommend potential improvements using new Snowflake features. For example, an AI Teammate tasked with maintaining strict performance targets could recommend deploying Snowflake Query Acceleration or Search Optimization Service to improve query performance. This reduces the need for System Administrators to constantly research, understand, and test new Snowflake features, reducing the dependency upon highly skilled (and expensive) resources.</p>
</li>
</ul>
<h3 id="heading-managing-snowflake-cluster-keys">Managing Snowflake Cluster Keys</h3>
<ul>
<li><p><strong>Identifying Clustering Opportunities:</strong> <a target="_blank" href="https://articles.analytics.today/snowflake-cluster-keys-and-micro-partition-elimination-best-practices">Snowflake Cluster Keys</a> can significantly impact Snowflake query performance, but deployment is more an art than a science. An AI Teammate could automatically analyze query patterns and data distribution to recommend adding, modifying, or removing cluster keys. For instance, if certain columns are frequently used in filter conditions but are not well clustered, the system could recommend creating cluster keys on those columns to speed up query performance.</p>
</li>
<li><p><strong>Monitoring Clustering Efficiency:</strong> As query workloads change over time, once appropriate cluster keys may become less efficient over time. For example, if a data pipeline changes, adds frequent <code>update</code> operations, or changes the data cardinality, this could make clustering less cost-effective. An AI Teammate could monitor the situation and recommend or even automatically deploy changes to improve query performance and optimize cost.</p>
</li>
</ul>
<h3 id="heading-dynamic-workload-allocation">Dynamic Workload Allocation</h3>
<p><a target="_blank" href="https://hashnode.com/edit/cm0a6anfv000509l4h9qk86ui"><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/325303f1-47a0-4cab-8c48-8e087c8c9018.png" alt /></a></p>
<p>The diagram above illustrates the overall challenge faced by System Administrators. Despite constantly increasing system workloads, we need to balance the conflicting needs to maximize system throughput (for example loading and transforming data), with maximizing end-user query performance (for example, delivering query results to analytics), and optimizing spend. Agentic AI can help with this challenge by automating system monitoring and adjusting workloads as needed.</p>
<p>The diagram below illustrates a typical mixed workload frequently found on Snowflake MEDIUM size warehouses.</p>
<p><a target="_blank" href="https://hashnode.com/edit/cm0a6anfv000509l4h9qk86ui"><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/53d64c65-2e85-45d8-8bf8-60fea0785299.png" alt /></a></p>
<p>While it's not obvious, research into <a target="_blank" href="https://blog.altimate.ai/simple-question-is-snowflake-expensive-the-answer-is-it-depends">Snowflake Workload Segmentation</a> demonstrates that the above workload would be more efficiently deployed over two or four warehouses, separating workloads by size and frequency. This has the potential to improve system performance and cost efficiency significantly.</p>
<p>Most customers deploy <a target="_blank" href="https://blog.altimate.ai/does-size-matter-what-else-is-important-in-choosing-a-snowflake-warehouse">workload separation</a> by team, which leads to poor utilization and high spending. AI Teammates constantly monitor jobs, recommending or even moving them to an appropriate warehouse size to achieve the best balance of throughput and cost efficiency.</p>
<p>For example, high-priority analytical workloads could be processed on larger warehouses while smaller, less important workloads could be shifted to more cost-effective, smaller warehouses configured for batch processing and prioritizing throughput and spend over individual query performance.</p>
<h3 id="heading-proactive-snowflake-monitoring-and-alerts"><strong>Proactive Snowflake Monitoring and Alerts</strong></h3>
<p>The screenshot below illustrates automated Snowflake cost monitoring across all sectors, including Warehouse computing, Storage, and Snowflake Serverless processing. AI agents can build upon basic monitoring to alert administrators proactively or take action.</p>
<p><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/a555bb5d-3575-4944-9a4b-ce71d16b61f6.png" alt class="image--center mx-auto" /></p>
<p><strong>Anomaly Detection</strong>: AI teammates can track the system’s performance and detect anomalies such as sudden spikes in query times, sudden increases in storage usage, or unexpected credit consumption.</p>
<p>Once detected, the system could either notify System Admins or attempt to automatically resolve the issue (e.g., by suggesting or implementing query optimizations).</p>
<p>In one case, a major Snowflake customer in the UK accidentally spent over $120,000 due to a simple manual configuration change that took a week to identify and resolve, which could have been automatically identified by an AI Teammate within seconds, potentially avoiding a significant bill.</p>
<h3 id="heading-end-to-end-elt-optimization"><strong>End-to-End ELT Optimization</strong></h3>
<p>According to Snowflake, automated data transformation tasks account for around 80% of customer spending. However, tuning increasingly complex pipelines can be remarkably resource-intensive, often requiring an army of highly skilled data engineers.</p>
<p>The diagram below illustrates the challenge with a simple transformation pipeline with potentially conflicting delivery timelines. The challenge comes from optimizing data delivery within the required SLA, but avoiding unnecessary processing.</p>
<p><a target="_blank" href="https://articles.analytics.today/how-snowflake-dynamic-tables-simplify-etl-pipelines"><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/0f9d99f7-0b69-4329-9780-442b32d8bdf5.png" alt /></a></p>
<p>In one example, a Snowflake customer in Munich, Germany was able to reduce overall system cost by 50% simply by suspending real-time analytics during out of hours. In short, if nobody is consuming the data, there's no need to produce it.</p>
<p>AI Teammates can help in the following ways:</p>
<ul>
<li><p><strong>Transformations and Load Efficiency</strong>: AI Teammates can analyze transformation pipelines, looking for inefficiencies or bottlenecks. They can recommend breaking down complex SQL statements into smaller tasks or <a target="_blank" href="https://articles.analytics.today/boost-your-snowflake-query-performance-with-these-10-tips">parallelizing operations</a> to improve load and transformation speeds.</p>
</li>
<li><p><strong>Dynamic Table Optimization</strong>: Snowflake's <a target="_blank" href="https://articles.analytics.today/how-snowflake-dynamic-tables-simplify-etl-pipelines">Dynamic Tables</a> massively simplify and streamline transformation pipelines with opportunities to dynamically change processing frequency and warehouse deployment. AI Teammates can automatically monitor both workload size and data consumption and adjust the pipeline configuration to balance and optimize performance and cost.</p>
</li>
<li><p>The diagram below illustrates one potential tuning step in which the ETL pipeline can be automatically adjusted to match changing the frequency at which data must be refreshed. In this case, a critical data feed is refreshed every five minutes. Once deployed, an AI Teammate can <a target="_blank" href="https://blog.altimate.ai/introducing-snowflake-dynamic-tables-what-you-need-to-know">automatically adjust the refresh frequency</a> for example reducing the frequency during out-of-hours to optimize cost.</p>
</li>
</ul>
<p><a target="_blank" href="https://articles.analytics.today/how-snowflake-dynamic-tables-simplify-etl-pipelines"><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/8d198b78-a8e4-4580-a4ce-eb46f9cd09c5.png" alt /></a></p>
<h2 id="heading-summary-amp-conclusion"><strong>Summary &amp; Conclusion:</strong></h2>
<p>AI Teammates in a Snowflake environment can act as intelligent assistants that continuously monitor and optimize various aspects of a Snowflake deployment.</p>
<p>They can provide actionable recommendations and potentially even implement changes themselves—whether it’s tuning queries, managing warehouse resources, or optimizing storage usage. This can lead to improved performance, reduced costs, and more efficient use of Snowflake’s powerful features, all with minimal manual intervention from human operators.</p>
<p>In conclusion, having spent nearly 10 years as a Senior Solution Architect much of that time working for Snowflake UK, I’ve a fair understanding of the huge challenges that Snowflake System Administrators face. I firmly believe that AI Teammates are indeed the secret to efficient Snowflake cost and performance management.</p>
<p>However, unlike the <a target="_blank" href="https://en.wikipedia.org/wiki/AI_takeover">pessimistic view</a> of Artificial Intelligence which warns about the machines taking over, the fact that AI Teammates work collaboratively with DBAs and Admins mean they’ll simply make an almost impossible task way more effective.</p>
<hr />
<p>Deliver more performance and cost savings with Altimate AI's cutting-edge AI teammates. These intelligent teammates come pre-loaded with the insights discussed in this article, enabling you to implement our recommendations across millions of queries and tables effortlessly. Ready to see it in action? Request a recorded demo by just sending a chat message (<a target="_blank" href="https://app.myaltimate.com/contactus">here</a>) and discover how AI teammates can transform your data teams.</p>
<p><a target="_blank" href="https://www.notion.so/altimate/Blog-Post-Demo-Hook-12041b89292680e09a26f8c718dbaad4?pvs=4"><img src="/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/d9ad5daf-6edc-4c94-a697-80f6cb79cbc5.png" alt class="image--center mx-auto" /></a></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/could-ai-teammates-be-the-secret-to-efficient-snowflake-cost-management/4f08497b-47c6-43da-96bc-8a3047f5b8fe.jpeg" type="image/jpeg" />
  </item>
  <item>
    <title>Write Better Data Docs Faster</title>
    <link>https://altimate.ai/blog/write-better-data-docs-faster</link>
    <guid isPermaLink="true">https://altimate.ai/blog/write-better-data-docs-faster</guid>
    <pubDate>Thu, 19 Sep 2024 07:22:34 GMT</pubDate>
    <dc:creator>Thomas Schmidt</dc:creator>
    <category>dbtpoweruser</category>
    <category>poweruserfordbt</category>
    <category>dbt</category>
    <category>datapilot</category>
    <category>altimateAI</category>
    <category>analytics</category>
    <category>vscode extensions</category>
    <category>dataengineering</category>
    <category>#ai-tools</category>
    <category>AI</category>
    <description>Once upon a time, an analyst in the trouble
Imagine Leila, an analyst, asked to build a monitoring dashboard for finance - given a tight deadline. While searching for a useful dataset, she comes across a table called “sh_monthly_revenue” that seems p...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/write-better-data-docs-faster/636afb0c-e89a-4e39-9349-d2597f224b4b.png" alt="Write Better Data Docs Faster" /></p>
<h2 id="heading-once-upon-a-time-an-analyst-in-the-trouble">Once upon a time, an analyst in the trouble</h2>
<p>Imagine Leila, an analyst, asked to build a monitoring dashboard for finance - given a tight deadline. While searching for a useful dataset, she comes across a table called “sh_monthly_revenue” that seems perfect based on its name and the columns it contains. However, there’s little documentation available, and the person who created it has already left the company. With time ticking, she makes a few assumptions based on the column names and dives into the analysis.</p>
<p>Weeks later, after presenting the dashboard findings, one of the business stakeholders points out that the data does not match the numbers in the financial reports at all. It turned out that the dataset she used wasn’t appropriate since it only covered revenue from a subset of customers, leading to incorrect assumptions and, ultimately, flawed conclusions. This scenario didn’t just waste time and resources - it also damaged Leila’s credibility and may have led to misguided business decisions.</p>
<p>If this sounds familiar, you’re not alone. Many data professionals - whether analysts, data scientists, or engineers - have found themselves in a similar situation. Poor documentation doesn’t just slow down work; it can lead to significant errors with far-reaching consequences. On the other hand, writing and maintaining comprehensive documentation can be a tedious and time-consuming task.</p>
<p>In this post, we’ll explore best practices for writing better documentation for your data models and how GenAI can help make the process less tedious and time-consuming. </p>
<h2 id="heading-good-documentation-matters-for-many-reasons">Good documentation matters for many reasons</h2>
<p>It’s easy to overlook documentation when you're in the final stages of building a data model, eager to push your work into production. We've all been there: you’ve just completed a model you’re proud of, and you’re ready to ship it out the door. But then comes the task of writing documentation (and possibly adding a few data tests). This critical step often gets rushed or skipped altogether, yet there are compelling reasons to take the time to do it right:</p>
<ul>
<li><p>Reduces time spent on data discovery</p>
</li>
<li><p>Reduces dependency on tribal knowledge</p>
</li>
<li><p>Reduces Ad-hoc questions you get from data consumers</p>
</li>
<li><p>Your org makes you follow governance and best practices guidelines ^_^</p>
</li>
</ul>
<p>Understanding why documentation matters is just the first step. The real challenge lies in consistently applying best practices to ensure your documentation is both comprehensive and usable. Let’s explore how you can achieve this with a few best practice tips.</p>
<h2 id="heading-best-practices-for-writing-excellent-data-documentation">Best practices for writing excellent data documentation</h2>
<p>Creating effective data documentation isn’t just about listing columns and definitions - it’s about ensuring that anyone who interacts with your data can understand and use it correctly, even if they have no prior context. Here are some best practices to help you design documentation that’s both comprehensive and user-friendly:</p>
<h3 id="heading-always-consider-the-readers-perspective">“Always Consider the Reader’s Perspective”</h3>
<p>When documenting a data model, it’s easy to fall into the trap of writing from your perspective, assuming that others will inherently understand the nuances you do. Instead, try to <strong>put yourself in the shoes of someone without prior knowledge of the dataset</strong>. When it comes to writing the docs for your model, you can follow these guidelines:</p>
<ul>
<li><p><strong>Clearly outline the Purpose and Utility:</strong> Define the key questions this dataset is designed to answer and the specific use cases it supports. This context helps users understand the data’s intent and how best to leverage it.</p>
</li>
<li><p><strong>Identify Caveats:</strong> Highlight any limitations or potential pitfalls associated with the data, such as missing information, known inaccuracies, or situations where the data might be misleading. These warnings are crucial for preventing misuse.</p>
</li>
<li><p><strong>Specify Granularity:</strong> Detail the level of detail provided by the data, whether it’s aggregated daily, weekly, or monthly, or at the transaction level or summarized. Understanding the granularity helps users determine the dataset’s appropriateness for their needs. In the case of columns, include information about primary keys, etc.</p>
</li>
<li><p><strong>Explain Contextual Background:</strong> Provide the reasoning behind the table’s creation, including any business processes or decisions that shaped its structure. This background helps users appreciate the dataset’s origins and relevance within the broader business context.</p>
</li>
<li><p><strong>Highlight Key Dimensions and Metrics:</strong> Point out the most important dimensions (such as date, location, and product) and metrics (like sales, revenue, and click-through rate) within the dataset. Explain how these elements interact and any specific considerations for their use. In the case of categorical columns, you can possibly include details about accepted values. </p>
</li>
<li><p><strong>Optimize for AI and Semantic Search:</strong> As AI tools become more integrated into data management, ensure your documentation includes relevant business terms, acronyms, and synonyms associated with the data. This optimization enhances discovery and usability, particularly for AI-driven tools like semantic search engines or analytics agents.</p>
</li>
</ul>
<p>Here is an example of how this could look like for our model from above:</p>
<p><img src="/blog/write-better-data-docs-faster/AD_4nXcKvq4t1tRZgpto-0wh9XNYWqhJcxTmhGTTaTLDZ5JrsgskbuGHbVRkn2hUKYayCUdmWnQjn_S6kBcXrP_4H3PuSBF87MhxLZLdolKlL9IAN-3Q4BUNFaRg62q3RncNZxCP5chG_6A3S5IgfWbmUc64Xlkh.jpg" alt /></p>
<h2 id="heading-make-documentation-less-painful-by-using-ai">Make documentation less painful by using AI</h2>
<p>Despite your best efforts, documentation can still be time-consuming and tedious, especially when balancing tight deadlines and complex data models. This is where generative AI (GenAI) comes into play, turning what once felt like a chore into a largely automated and streamlined process. </p>
<p>Tools like the <a target="_blank" href="https://docs.myaltimate.com/document/generatedoc/">Power User for dbt (DataPilot)</a> are designed to handle the heavy lifting of documentation, automatically generating detailed table and column descriptions from your existing data models. These tools use the metadata context available in your environment automatically like schema information, column lineage etc. and write so good documentation that has surprised me many times. Some of the key features include:</p>
<ul>
<li><p><strong>Effortlessly Document Hundreds of Columns:</strong><br />  Have 900 columns to document? No problem. With <strong>bulk generation</strong>, you can quickly create reliable descriptions for every column, allowing you to focus your efforts on refining and curating the details that matter most.</p>
</li>
<li><p><strong>Tailored Documentation for Different Audiences:</strong><br />  The extension allows you to <strong>generate documentation for different user personas</strong>. Use technical language for your intermediate layer tables and a more business-friendly tone for end-user-facing tables. This ensures that each audience gets the information they need in the most effective format.</p>
</li>
<li><p><strong>Seamless Integration with Your Workflow:</strong><br />  The tool <strong>integrates directly with your dbt YAML schemas</strong>, injecting newly generated documentation into existing schemas or updating current documentation with just a few clicks. All this happens directly within the model SQL file, so you can avoid those days when your IDE tabs blow up like confetti due to the number of open file tabs.</p>
</li>
</ul>
<p>More details can be found <a target="_blank" href="https://docs.myaltimate.com/document/generatedoc/">here</a></p>
<p>Overall, documentation is an important aspect of analytics engineering and it’s essential that we follow best practices, otherwise, we run the risk of writing documentation for namesake or not writing it at all! GenAI based automation is going to be the major boon in this area, it has its kinks but early signs are very promising making me quite excited for the future!</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/write-better-data-docs-faster/636afb0c-e89a-4e39-9349-d2597f224b4b.png" type="image/png" />
  </item>
  <item>
    <title>Can AI Agents reduce Snowflake Cost using Dynamic Tables?</title>
    <link>https://altimate.ai/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables</link>
    <guid isPermaLink="true">https://altimate.ai/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables</guid>
    <pubDate>Sat, 07 Sep 2024 07:25:12 GMT</pubDate>
    <dc:creator>John Ryan</dc:creator>
    <category>Snowflake Costs</category>
    <category>snowflake</category>
    <category>ai agents</category>
    <category>Artificial Intelligence</category>
    <description>In my previous article on Dynamic Tables, I explained their purpose, to help simplify building transformation pipelines for either batch or real time data feeds in Snowflake. In this article, I&apos;ll explain what they cost to run and how Artificial Inte...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/459f1d62-c8a1-4a4e-b796-10d83512baa3.jpeg" alt="Can AI Agents reduce Snowflake Cost using Dynamic Tables?" /></p>
<p>In my previous article on <a target="_blank" href="https://blog.altimate.ai/introducing-snowflake-dynamic-tables-what-you-need-to-know">Dynamic Tables</a>, I explained their purpose, to help simplify building transformation pipelines for either batch or real time data feeds in Snowflake. In this article, I'll explain what they cost to run and how <a target="_blank" href="http://blog.altimate.ai/will-ai-agents-replace-snowflake-system-administrators">Artificial Intelligent Agents</a> can be used to automatically monitor, alert and even deploy remedial action to control cost.</p>
<p>Skeptical? Read on to see how to reduce the annual cost of running three Dynamic Tables from $6.3m to just $26,280.</p>
<h2 id="heading-dynamic-tables-cost-components">Dynamic Tables Cost Components</h2>
<p>It may not be obvious but Dynamic Tables include multiple cost elements including:</p>
<ul>
<li><p><strong>Cloud Compute:</strong> Dynamic Tables are automatically refreshed on a repeating sequence depending upon the TARGET_LAG. For example, once per minute or once per hour.</p>
</li>
<li><p><strong>Data Storage:</strong> Like any table, Dynamic Tables store data, and this will be billed at £23 per terabyte per month.</p>
</li>
<li><p><strong>Warehouse Cost:</strong> Every time the Dynamic Table is refreshed it (currently) needs a <a target="_blank" href="https://articles.analytics.today/snowflake-virtual-warehouses-what-you-need-to-know">Virtual Warehouse</a> to execute the SQL, and this is billed on a per-second basis with a minimum of 60 seconds.</p>
</li>
</ul>
<p>Let's consider each of these elements and it's potential impact upon the overall cost of ownership.</p>
<h2 id="heading-cloud-compute-cost">Cloud Compute Cost</h2>
<p>This is by far the least expensive of the three cost elements and results from the automatic scheduling executed in the <a target="_blank" href="https://docs.snowflake.com/en/user-guide/intro-key-concepts#cloud-services">Cloud Services</a> layer. Determined by the TARGET_LAG, the DT "wakes up" and checks if there any changes in the upstream table(s). This is likely to be thousands of a dollar each time, and for 99% of customers is free, unless it becomes more than 10% of your daily warehouse cost.</p>
<p>In short, don't worry about this.</p>
<h2 id="heading-dynamic-table-storage-cost">Dynamic Table Storage Cost</h2>
<p>While you need to store data in Snowflake (and therefore you'll be billed a passthru cost of £23 per terabyte), it's not clear that Dynamic Tables add to the <a target="_blank" href="https://articles.analytics.today/how-to-cut-snowflake-data-storage-costs-with-zero-copy-clones">storage cost</a>. Consider the diagram below.</p>
<p><img src="/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/d46b86b5-66e5-4fa5-9ddd-997a95f959f5.png" alt class="image--center mx-auto" /></p>
<p>In the above diagram tables T1 and T2 are default tables, wheres T3, T4 and T5 are dynamic tables. If we assume T1 and T2 hold 1TB of data storage, and the transformation to T3 and T4 is simply to perform a basic data quality correction (for example, setting in incorrect SALES_TYPE column to NULL when the values are incorrect), then tables T3 and T4 will equally hold around 1TB of storage.</p>
<p>If the results of T3 and T4 are then combined using a JOIN operation into a single table T5 - ready for querying, this adds another 2TB to storage.</p>
<p>In total we store 6TBs of storage.</p>
<p>However, if we were not using Dynamic Tables, then tables T1 and T2 could be deleted down each time the new entries where processed. Likewise, once the process to join the tables and produce T5 was complete, tables T3 and T4 could be deleted.</p>
<p>This means, a solution without Dynamic Tables could deploy the same functionality in 2TBs compared to 6 TBs.</p>
<p>Data storage is a relatively minor cost on most Snowflake systems, but it's a cost worth understanding.</p>
<h2 id="heading-dynamic-tables-warehouse-cost">Dynamic Tables Warehouse Cost</h2>
<p>This is almost certainly the greatest cost associated with Dynamic Tables, although unlike the data storage example above, there's no additional cost when compared to a transformation pipeline without DTs.</p>
<p>Effectively, each time a Dynamic Table triggers a refresh (provided there's changed data in the upstream tables), Snowflake executes the associated SQL on a Virtual Warehouse. However, even this has a potential gotcha. Consider again the diagram below.</p>
<p><img src="/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/03f5b2a6-bc24-4933-ac5f-a325a7f7c9b0.png" alt class="image--center mx-auto" /></p>
<p>The diagram above illustrates the same transformation pipeline, with two source tables and three dynamic tables. Notice that two of the tables are marked as Downstream? This means their refresh rate is determined by the downstream table - in this case a table refreshed every minute.</p>
<p>Let's assume new data is automatically inserted into the Sales table using <a target="_blank" href="https://docs.snowflake.com/en/user-guide/data-load-snowpipe-intro">Snowpipe</a> which runs on a 24x7 basis. The Stores data is however, refreshed once per day.</p>
<p>Can you see what might happen to the cost profile of this simple transformation pipeline?</p>
<p>As new sales are automatically loaded into the Sales table (T1), Dynamic Tables T3 and T5 are automatically refreshed based upon the one minute TARGET_LAG.</p>
<p>Let's assume all Dynamic Tables were initially deployed on an XSMALL warehouse, this incredibly simple transformation pipeline would cost up to $1,576,800 per year. Worse still, if the warehouse was subsequently <a target="_blank" href="https://articles.analytics.today/snowflake-virtual-warehouses-is-bigger-faster-but-more-expensive">increased</a> in size to a MEDIUM, this would increase to a shocking $6.3m a year for a single warehouse.</p>
<p>Around four years ago, I did a consultancy visit to a customer in Munich Germany who had deployed a similar pipeline, also running 24x7 and were shocked by the high cost. The customer justified the 24x7 operation because the system tracked global internet based sales, and could therefore receive sales 24x7.</p>
<p>After some time on the whiteboard to map out the equally simple pipeline, I understood the problem and asked the customer - "<strong><em>So, where are your Data Analysts based</em></strong>".</p>
<p>I'm sure they thought it was a stupid question, as their reply was like talking to a five year-old. "<strong><em>Here in Munich, John</em></strong>".</p>
<p>In response, I asked whether the Data Analysts were looking at the data at 4am, and if not, why were we processing data at 4am and paying for a virtual warehouse to wake up every minute leading to a huge bill?</p>
<p>Finally, I also questioned, why they were continuously processing data every minute. What action would the analysts take that needed the data to be as little as one minute stale?</p>
<p>In conclusion, the same transformation pipeline cost, even on a MEDIUM size warehouse could be cut by 50%, simply by suspending the Dynamic Table refresh from 8pm to 8am using a <a target="_blank" href="https://docs.snowflake.com/en/sql-reference/sql/create-task">Snowflake Task</a>.</p>
<p>We could further reduce the cost by a factor of four by executing the following SQL statements.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">alter</span> dynamic <span class="hljs-keyword">table</span> T3 
   <span class="hljs-keyword">set</span> warehouse = DT_XSMALL_WAREHOUSE;
<span class="hljs-keyword">alter</span> dynamic <span class="hljs-keyword">table</span> T4
   <span class="hljs-keyword">set</span> warehouse = DT_XSMALL_WAREHOUSE;
</code></pre>
<p>The two simple SQL statements move the refresh operation to an XSMALL warehouse costing 25% of the cost. Of course, we'd need to check the refresh performance was acceptable, but assuming an INCREMENTAL refresh method, this should be pretty fast to complete.</p>
<p>Finally, we should question whether the Data Analytics <strong>really need</strong> the data refreshed every minute. Executing the following SQL would reduce costs by a factor of 60.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">alter</span> dynamic <span class="hljs-keyword">table</span> T5
   <span class="hljs-keyword">set</span> target_lag = <span class="hljs-string">'1 Hour'</span>;
</code></pre>
<blockquote>
<p>"Never give a user what they <strong>ask for</strong>, give them what they <strong>need</strong>" - Dr. David Pearson.</p>
</blockquote>
<h2 id="heading-can-artificial-intelligence-help">Can Artificial Intelligence Help?</h2>
<p>As I've described before, a new breed of <a target="_blank" href="http://blog.altimate.ai/will-ai-agents-replace-snowflake-system-administrators">Artificial Intelligent Agents</a> can be used to tirelessly monitor, alert or even adjust system configuration. It's like having an Artificially Intelligent Database Administrator proactively tuning your system.</p>
<p>However, the challenge of tuning a multi-petabyte analytic platform which charges using a pay-for-use basis is more challenging that you'd expect.</p>
<p><img src="/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/afef2d09-b0a6-43a7-9a80-b332486ec93d.png" alt class="image--center mx-auto" /></p>
<p>The diagram above illustrates the primary challenge, balancing the need to maximize throughput of large (mainly batch) transformation jobs, and maximizing performance of end-user queries while also optimizing spend.</p>
<p>There are also some critical facts about Snowflake which need to be understood:</p>
<ol>
<li><p>Around 80% of the cost of running a Data Warehouse comes from repeating automated jobs. The majority of these tend to be batch oriented and many prioritize throughput over performance - the need to regularly deliver data, perhaps once per hour or once per day.</p>
</li>
<li><p>Years of research with over 50 Snowflake customers and thousands of queries against real customer data have demonstrated that most customers have a poor <a target="_blank" href="https://blog.altimate.ai/does-size-matter-what-else-is-important-in-choosing-a-snowflake-warehouse">virtual warehouse deployment</a> strategy which potentially leads to significant cost overspend.</p>
</li>
<li><p><a target="_blank" href="https://articles.analytics.today/how-snowflake-dynamic-tables-simplify-etl-pipelines">Snowflake Dynamic Tables</a> have the fastest growth in uptake of any Snowflake feature and are likely to become the gold standard for data transformation on Snowflake. However, unlike hand-coded ELT jobs, the warehouse size and execution frequency can be easily adjusted as these are entirely configurable in the Dynamic Table definition.</p>
</li>
</ol>
<p>Taking both the problem (balancing throughput, performance and cost), with the configurable nature of Dynamic Tables means it's possible to automatically monitor and even change system configuration in real-time using <a target="_blank" href="http://blog.altimate.ai/will-ai-agents-replace-snowflake-system-administrators">Agenic AI</a>.</p>
<p><img src="/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/da531430-f6fc-4a5e-bbae-f2c156e49d2f.png" alt class="image--center mx-auto" /></p>
<p>The screenshot above shows the frequency of AI Agent decisions used to monitor and adjust Snowflake to maximize performance and optimize costs.</p>
<p>For example, if an ELT pipeline normally needs a MEDIUM sized warehouse but regular end-of-month processing would justify an X4LARGE, an <a target="_blank" href="http://blog.altimate.ai/will-ai-agents-replace-snowflake-system-administrators">AI Agent</a> could automatically identify the opportunity and even change the configuration subject to System Administrator approval. This would not only deliver results over 100 times faster, but it would avoid a common mistake made by almost every Snowflake customer, using an i<a target="_blank" href="https://blog.altimate.ai/does-size-matter-what-else-is-important-in-choosing-a-snowflake-warehouse">nappropriate virtual warehouse size</a>, and effectively the largest possible machine for the highest expected workload.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>While the cost of Cloud Services compute and even storage for Dynamic Tables is likely to negligible, we need to consider the cost of running a virtual warehouse.</p>
<p>With just three SQL statements, we reduced the maximum cost of this simple transformation pipeline from $6.3m per year down to $26,280.</p>
<p>To summarize what we learned:</p>
<ul>
<li><p><strong>Cloud Compute and Storage</strong> costs can (in most cases) be ignored. They shouldn't add significant cost to a pipeline deployed using a Dynamic Table.</p>
</li>
<li><p><strong>Warehouse Costs</strong> however, can be remarkably high and lead to an eye-watering annual bill if deployed without thought.</p>
</li>
<li><p><strong>Snowflake is not expensive!</strong> Like any tool, if used incorrectly it can lead to a poor outcome. Applying some common sense goes a long way.</p>
</li>
<li><p><strong>TARGET_LAG:</strong> Is critical in determining the frequency with which a Dynamic Table query is executed. If the data changes frequently, it can lead to significant cost. Carefully choose a TARGET_LAG based on how fresh you <strong>need</strong> the data. Don't just set it to once per minute because you can.</p>
</li>
<li><p><strong>Dynamically Change the lag:</strong> You can set up a simple schedule to suspend Dynamic Table refreshes or adjust the TARGET_LAG during off-peak or holiday periods. Suspending the refresh overnight will immediately reduce the costs by up to 50%.</p>
</li>
</ul>
<p>Finally, in addition to manually adjusting Dynamic Table configuration, we could deploy <a target="_blank" href="http://blog.altimate.ai/will-ai-agents-replace-snowflake-system-administrators">AI Agents</a> to autonomously monitor, alert or even tune Dynamic Tables to automatically achieve the almost impossibly complex goal of balancing the requirements of throughput, performance and cost.</p>
<hr />
<p>Deliver more performance and cost savings with Altimate AI's cutting-edge AI teammates. These intelligent teammates come pre-loaded with the insights discussed in this article, enabling you to implement our recommendations across millions of queries and tables effortlessly. Ready to see it in action? Request a recorded demo by just sending a chat message (<a target="_blank" href="https://app.myaltimate.com/contactus">here</a>) and discover how AI teammates can transform your data teams.</p>
<p><a target="_blank" href="https://app.myaltimate.com/contactus"><img src="/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/d9ad5daf-6edc-4c94-a697-80f6cb79cbc5.png" alt /></a></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/can-ai-agents-reduce-the-cost-of-snowflake-dynamic-tables/459f1d62-c8a1-4a4e-b796-10d83512baa3.jpeg" type="image/jpeg" />
  </item>
  <item>
    <title>How I Cut dbt Development Time by 20% with the Power User Vscode Extension</title>
    <link>https://altimate.ai/blog/how-i-cut-dbt-development-time-by-20-with-the-power-user-vscode-extension</link>
    <guid isPermaLink="true">https://altimate.ai/blog/how-i-cut-dbt-development-time-by-20-with-the-power-user-vscode-extension</guid>
    <pubDate>Sun, 14 Apr 2024 23:47:22 GMT</pubDate>
    <dc:creator>Anand Kumar</dc:creator>
    <category>dbt</category>
    <category>datapilot</category>
    <category> analytics tools</category>
    <category>devtools</category>
    <category>vscode extensions</category>
    <description>Working with data in any capacity—be it as a data/analytics engineer, data scientist, or data analyst—inevitably dealing with the need for documentation. Whether it&apos;s clarifying unclear fields, understanding dataset structures, or seeking explanation...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/how-i-cut-dbt-development-time-by-20-with-the-power-user-vscode-extension/56f8f767-b124-4eaa-ab9e-8d96c5d5b03e.webp" alt="How I Cut dbt Development Time by 20% with the Power User Vscode Extension" /></p>
<p>Working with data in any capacity—be it as a data/analytics engineer, data scientist, or data analyst—inevitably dealing with the need for documentation. Whether it's clarifying unclear fields, understanding dataset structures, or seeking explanations for data discrepancies, clear and comprehensive documentation is important. In the constantly evolving data world, where accuracy and clarity are non-negotiable, tools like dbt (data build tool) emerge as lifesavers.</p>
<p>Recognizing the importance of clear documentation in the data world, dbt™ makes documentation significantly easier through its dbt™ docs feature.</p>
<p>dbt provides a way to generate documentation for your dbt™ project. The documentation for your project includes:</p>
<ul>
<li><p>Project Information: including model code, a DAG of your project, any tests you've added to a column, and more.</p>
</li>
<li><p>Data warehouse Information: including column data types, and table sizes. This information is generated by running queries against the information schema.</p>
</li>
</ul>
<p>A standout feature of dbt™ lies in its capability to enhance documentation comprehensively. Users can add detailed descriptions to models, columns, sources, and other project elements, enriching the documentation with context and clarity. This not only aids in understanding the data structures but also streamlines collaboration and knowledge sharing within teams.</p>
<p>Here's an example of how dbt™ models can be documented:</p>
<pre><code class="lang-yaml">
<span class="hljs-attr">version:</span> <span class="hljs-number">2</span>

<span class="hljs-attr">models:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">events</span>
    <span class="hljs-attr">description:</span> <span class="hljs-string">This</span> <span class="hljs-string">table</span> <span class="hljs-string">contains</span> <span class="hljs-string">clickstream</span> <span class="hljs-string">events</span> <span class="hljs-string">from</span> <span class="hljs-string">the</span> <span class="hljs-string">marketing</span> <span class="hljs-string">website</span>

    <span class="hljs-attr">columns:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">event_id</span>
        <span class="hljs-attr">description:</span> <span class="hljs-string">This</span> <span class="hljs-string">is</span> <span class="hljs-string">a</span> <span class="hljs-string">unique</span> <span class="hljs-string">identifier</span> <span class="hljs-string">for</span> <span class="hljs-string">the</span> <span class="hljs-string">event</span>
        <span class="hljs-attr">tests:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">unique</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">not_null</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">user-id</span>
        <span class="hljs-attr">quote:</span> <span class="hljs-literal">true</span>
        <span class="hljs-attr">description:</span> <span class="hljs-string">The</span> <span class="hljs-string">user</span> <span class="hljs-string">who</span> <span class="hljs-string">performed</span> <span class="hljs-string">the</span> <span class="hljs-string">event</span>
        <span class="hljs-attr">tests:</span>
          <span class="hljs-bullet">-</span> <span class="hljs-string">not_null</span>
</code></pre>
<p><strong>Overcoming Documentation Challenges</strong></p>
<p>Despite the robust dbt™ docs feature, documentation often takes a backseat due to the inherent gap between project work and the documentation process. After completing a model, users frequently find themselves navigating to various directories to locate and manually edit schema YAML files for documentation purposes. This manual approach is time-consuming and prone to errors, relying heavily on individual skills and consistency.</p>
<p><strong>Introducing Power User for dbt Extension: A Game-Changer in Documentation</strong></p>
<p>To address these challenges and streamline the documentation workflow, Altimate AI introduces the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-dbt-power-user">Power User for dbt</a> vscode extension. This extension leverages AI capabilities to revolutionize documentation generation, making it a seamless and efficient process. Specifically, Altimate AI is designed to emulate the behavior of human engineers by leveraging contextual insights drawn from schema, sources, column-level lineage, metadata, and existing documents to create tailored documentation, rather than just generating generic documentation.</p>
<p>Within the documentation editor, users can access a range of functionalities:</p>
<ol>
<li><p><strong>Model Documentation</strong>: Users can edit individual model documentation directly within the editor, eliminating the need for manual YAML editing. Additionally, AI-driven generation allows for instant and accurate descriptions, tailored to specific use cases such as professional or more casual documentation styles</p>
<p> <img src="/blog/how-i-cut-dbt-development-time-by-20-with-the-power-user-vscode-extension/e72f8a02-7db3-4bcf-883c-ab502b590b07.png" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Column Documentation</strong>: The extension enables users to generate detailed documentation for individual columns, automatically saving them in the 'schema.yml' file with the appropriate syntax. This automation not only accelerates development but also ensures consistency and accuracy across documentation.</p>
<p> <img src="/blog/how-i-cut-dbt-development-time-by-20-with-the-power-user-vscode-extension/aeb5acc4-4e29-4fd1-8e72-2527b84f12c9.jpeg" alt class="image--center mx-auto" /></p>
</li>
<li><p><strong>Multiple Languages Documentation</strong>: Users have the flexibility to create documentation in several languages, including French, English, Dutch, and German. This feature enables the generation of content that caters to diverse linguistic needs.</p>
</li>
<li><p><strong>Persona-Specific Documentation:</strong> The extension offers a variety of presets designed for different audiences. Users can select the persona that best matches their needs, whether it be a technical user, business user, or general user. For general users, the documentation is crafted without a specific persona focus, ensuring it is accessible and understandable to a broad audience.</p>
</li>
</ol>
<p><strong>Impact of Effective Documentation in dbt™</strong></p>
<p>Quality documentation significantly improves how models are used and reduces unnecessary communications between teams, boosting productivity. Using the dbt Power User extension, you can save at least two minutes per column in documentation tasks. Depending on the size and complexity of the models, this efficiency can lead to a reduction of 10%-20% in development expenses. This not only translates to substantial cost savings but also frees up engineers to focus on more critical tasks.</p>
<p><strong>Harnessing the Power of AI for Documentation Excellence</strong></p>
<p>Maintaining documentation in a dynamic data environment presents a substantial challenge. As business requirements expand and projects evolve, the task of updating documentation to reflect changes in models, schemas, or sources becomes increasingly complex and resource-intensive. This constant need for updates can significantly drain time and productivity. Hence, the integration of AI-driven documentation generation within dbt Power User extension represents a significant advancement in data documentation practices. By automating tedious tasks and offering customizable options, dbt™ enables engineers to concentrate on development work while ensuring that the documentation stays comprehensive and up-to-date.</p>
<p><strong>Final Thoughts</strong></p>
<p>In the rapidly changing world of data management, understanding the essence of quality documentation has never been more critical, dbt Power User extension documentation capabilities shine as a beacon of efficiency and excellence. By leveraging advanced technologies like AI, dbt Power User extension not only simplifies the documentation process but also promotes data transparency, collaboration, and innovation. Embracing these powerful tools paves the way for enhanced productivity, informed decision-making, and data-driven success.</p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/how-i-cut-dbt-development-time-by-20-with-the-power-user-vscode-extension/56f8f767-b124-4eaa-ab9e-8d96c5d5b03e.webp" type="image/webp" />
  </item>
  <item>
    <title>Optimizing Snowflake Queries : Expert Strategies for Data Engineers and Analysts</title>
    <link>https://altimate.ai/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts</link>
    <guid isPermaLink="true">https://altimate.ai/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts</guid>
    <pubDate>Sun, 28 Jan 2024 21:01:29 GMT</pubDate>
    <dc:creator>John Ryan</dc:creator>
    <category>Snowflake performance</category>
    <category>Performance Tuning</category>
    <category>snowflake</category>
    <category>data-engineering</category>
    <category>data analyst</category>
    <category>generative ai</category>
    <category>AI</category>
    <description>For data teams, the clock is always ticking. In a business landscape defined by rapidly expanding datasets, slow queries can grind insights to a halt. That&apos;s why performance tuning is especially critical when working with a platform like Snowflake. T...</description>
    <content:encoded><![CDATA[<p><img src="https://altimate.ai/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/3bc6e31d-4dc7-49e5-9e4e-cc8cadce929c.png" alt="Optimizing Snowflake Queries : Expert Strategies for Data Engineers and Analysts" /></p>
<p>For data teams, the clock is always ticking. In a business landscape defined by rapidly expanding datasets, slow queries can grind insights to a halt. That's why performance tuning is especially critical when working with a platform like Snowflake. This platform, renowned for its lack of traditional indexes, presents unique challenges and opportunities for optimizing query performance. To navigate these uncharted waters, data engineers and analysts need a mastery of specialized optimization tactics. Join me as we dive into the art of writing fast code that unlocks the full capabilities Snowflake offers. We’ll review examples ranging from basic query tuning to more advanced optimizations that can mean the difference between swift analytics and stalled projects.</p>
<h2 id="heading-snowflake-performance-tuning-strategy">Snowflake Performance Tuning Strategy</h2>
<p>Before we start, let’s put the overall performance-tuning strategy in context.  The diagram below illustrates the typical data processing pipeline you’ll see on any Snowflake platform, which consists of the following:</p>
<ul>
<li><p><strong>Data Loading:</strong> This involves copying data from Cloud Storage into a Table Landing zone.  This normally uses the Snowflake COPY or SNOWPIPE commands.</p>
</li>
<li><p><strong>Data Transformation:</strong>  Data from multiple sources and loading into Data Integration and Data Delivery zones.  This involves the execution of Insert, Update, or Merge statements to clean, manipulate, and transform the data ready for consumption.</p>
</li>
<li><p><strong>Data Querying &amp; Consumption:</strong>  The data by end user dashboards, reports, or analysis.  This typically involves SELECT statements against the Data Delivery zone.</p>
</li>
</ul>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/2895c1aa-1647-4c35-81f0-1b92ac6b61c5.png" alt class="image--center mx-auto" /></p>
<p>It’s worth considering the above because the approach and solutions tend to differ. Let’s consider each in turn.</p>
<h2 id="heading-data-delivery">Data Delivery</h2>
<p>As indicated above, data delivery is all about quickly using SELECT statements to deliver results to end-users.  This means it's vital SQL is tuned for maximum performance.  When tuning query performance, the first place to look is the query profile.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/5cf4a64f-0099-4ded-a83d-89217106c831.png" alt class="image--center mx-auto" /></p>
<p>The screenshot above illustrates the first place to check for performance issues.  Many assume this indicates the time spent, but it's the time waiting for resources.</p>
<p>The above case shows the query spent just 10% of its time waiting on CPU resources, almost zero (0.2%) of the time waiting for Local Disk I/O to complete, but nearly 90% of the time waiting on Remote Disk I/O.</p>
<p>Reviewing the overall Snowflake hardware architecture illustrated in the diagram below is helpful to understand what this means.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/fa996e5a-9937-420d-81bd-76a2339aae39.png" alt class="image--center mx-auto" /></p>
<p>The above diagram shows how queries submitted to Snowflake are handled by the Cloud Services Layer, determining the best way to execute the query.  The SQL is then passed to a Virtual Warehouse, a physical computer with CPU cores, memory, and SSD (Local) storage.</p>
<p>When queries are executed, the data is read from Remote Storage, cached in SSD, and results computed and returned to the user.</p>
<p>The key insight here is that (SSD) Local Storage is hundreds of times faster than Remote (disk) storage.  One of the most effective ways to maximize query performance is limiting Remote Disk accesses.</p>
<p>The most effective way to reduce remote disk I/O is using the query WHERE clause to filter out rows. Complex SQL queries often include a series of Common Table Expressions (CTEs or inline views), and the best practice is to filter out rows as early as possible.  The fewer rows fetched from the Remote Disk, the faster the query executes.</p>
<p>The next step in tuning Snowflake query performance is to review the query statistics illustrated in the screenshot below.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/25c3900b-0838-4817-905d-247da9bdf125.png" alt class="image--center mx-auto" /></p>
<p>Snowflake stores data in 16MB blocks called micro partitions and automatically prunes these to maximize query performance, but it's entirely dependent upon the WHERE clause.  If (for example), a query includes no WHERE clause, Snowflake will need to fetch the entire table from Local or Remote storage with a significant impact upon performance.</p>
<h2 id="heading-tuning-the-query-where-clause">Tuning the query WHERE clause</h2>
<p>You can make simple changes to the WHERE clause to maximize query performance.  Take, for example, the following SQL statement:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> SNOWFLAKE_SAMPLE_DATA.TPCH_SF1000.ORDERS
<span class="hljs-keyword">where</span> to_char(o_orderdate,<span class="hljs-string">'DD-MON-YYYY'</span>) = <span class="hljs-string">'01-APR-1992'</span>;
</code></pre>
<p>The above query returns ORDERS placed on 1st April 1992.  However, we limited Snowflake's ability to prune query performance automatically because we formatted the O_ORDERDATE as a character in the WHERE clause.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> SNOWFLAKE_SAMPLE_DATA.TPCH_SF1000.ORDERS
<span class="hljs-keyword">where</span> o_orderdate = <span class="hljs-keyword">to_date</span>(<span class="hljs-string">'01-APR-1992'</span>,<span class="hljs-string">'DD-MON-YYYY'</span>);
</code></pre>
<p>The above query produces the same result ten times faster, completing in under four seconds instead of nearly 40 seconds.  The reason is we left the O_ORDERDATE column unmodified.</p>
<p>Surprisingly, despite converting a DATE to a CHARACTER field, Snowflake can still perform some partition pruning.  However, modifying WHERE clause columns using a user-defined function will almost certainly lead to a full table scan.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> orders
<span class="hljs-keyword">where</span> format_date_udf(o_orderdate,<span class="hljs-string">'DD-MON-YYYY'</span>) = <span class="hljs-string">'01-APR-1992'</span>;
</code></pre>
<p>The above query will perform even worse as Snowflake cannot evaluate the output of a User-Defined Function and will always lead to a full table scan.</p>
<h2 id="heading-tuning-sort-operations">Tuning Sort Operations</h2>
<p>Designing an analytics solution without including an ORDER BY or GROUP BY clause in the query is almost impossible.  However, sorts are the most computationally expensive operations and are often the most significant cause of query performance issues.</p>
<p>Often, data analysts need to determine whether a given column is unique and will execute the following SQL:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> <span class="hljs-keyword">count</span>(<span class="hljs-keyword">distinct</span> l_orderkey)
<span class="hljs-keyword">from</span> snowflake_sample_data.tpch_sf1000.lineitem;
</code></pre>
<p>However, the following query will execute around 600% faster with an accuracy of around 99%:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> count_approx_distinct(l_orderkey)
<span class="hljs-keyword">from</span> snowflake_sample_data.tpch_sf1000.lineitem;
</code></pre>
<p>The COUNT_APPROX_DISTINCT is one of a series of approximation functions that accurately estimate large data volumes orders of magnitude faster.</p>
<h2 id="heading-dealing-with-high-cardinality-data">Dealing with high-cardinality data</h2>
<p>While dealing with large data volumes is often necessary, you should be especially careful when sorting high cardinality data, for example, by a unique key.  Take, for example, the following SQL statements, which appear similar but have wildly different query performance.</p>
<h3 id="heading-query-1-unique-key">Query 1 - Unique Key</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> o_orderkey,
       <span class="hljs-keyword">sum</span>(o_totalprice)
<span class="hljs-keyword">from</span> orders
<span class="hljs-keyword">group</span> <span class="hljs-keyword">by</span> <span class="hljs-number">1</span>;
</code></pre>
<h3 id="heading-query-2-low-cardinality">Query 2 - Low Cardinality</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> o_orderpriority,
       <span class="hljs-keyword">sum</span>(o_totalprice)
<span class="hljs-keyword">from</span> orders
<span class="hljs-keyword">group</span> <span class="hljs-keyword">by</span> <span class="hljs-number">1</span>;
</code></pre>
<p>You may be surprised to find that query 2 (Low Cardinality) runs around 22 times faster than query 1 (Unique Key), as illustrated in the screenshot below:</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/d305518c-b8d6-434c-bc66-1048845ebc17.png" alt class="image--center mx-auto" /></p>
<p>The reason for the huge query performance difference is that Query 1 - Unique Key (which takes over six minutes to complete), includes a GROUP BY on a column with 1.5 billion unique values whereas Query 2 - Low Cardinality (executing in 11 seconds) has just five distinct values.</p>
<p>In this case, the best practice is to be aware of the high cost of sort operations and avoid GROUP BY or ORDER BY operations on highly unique keys.</p>
<h2 id="heading-using-the-snowflake-limit-or-top-option">Using the Snowflake LIMIT or TOP option</h2>
<p>There are sometimes use cases where we need to ORDER very large data volumes by unique keys, but it’s still possible to improve query performance using the simple LIMIT or TOP options on SELECT statements.</p>
<p>Consider the following SQL statements:</p>
<h3 id="heading-query-1-order-by-every-row">Query 1 - Order by Every Row</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> lineitem
<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> l_quantity;
</code></pre>
<h3 id="heading-query-2-order-by-with-limit">Query 2 - Order by With Limit</h3>
<pre><code class="lang-sql"><span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> lineitem
<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> l_quantity
<span class="hljs-keyword">limit</span> <span class="hljs-number">10</span>;
</code></pre>
<p>Using the LIMIT 10 option on Query 2 (only first ten rows), leads to an 11 times improvement in query performance from over 17 minutes to just 1m 35s.</p>
<p>The reason for the huge difference in query performance is revealed in the Query Plan.  Query 1 (Order by every row) on the left includes a <strong>Sort</strong> operation that returns 600 million rows, whereas Query 2 (order by with limit) on the right uses a <strong>SortWithLimit</strong> operation to reduce the entries from 600m to just 10.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/3fb85130-b7cd-44bc-adbb-71c81ec432dd.png" alt class="image--center mx-auto" /></p>
<p>Another significant contributor to the query performance is that the Order by with limit scans half the number of micro-partitions and eliminates spilling to storage, significantly reducing query execution time.</p>
<h2 id="heading-spilling-to-storage">Spilling to Storage</h2>
<p>The diagram below illustrates the internal structure of an XSMALL virtual warehouse.  It (currently) consists of eight CPU cores, gigabytes of memory, and hundreds of gigabytes of fast SSD storage attached to slower Remote Storage.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/46f4fec1-af60-41d5-a4ff-8201a020905d.png" alt class="image--center mx-auto" /></p>
<p>hen Snowflake executes a query with an ORDER BY or GROUP BY clause, it must sort the results it attempts to complete in super-fast main memory.  However, sorting large data volumes in a smaller warehouse runs out of memory and needs to spill working data to SSD, which is thousands of times slower.</p>
<p>When sorting even bigger data volumes, it may need to spill to Remote Storage, which is many hundreds of times slower again.</p>
<p>It’s good practice to avoid spilling to storage where possible, but how to do this?</p>
<p>There are several Snowflake best practice tuning strategies to avoid spilling to storage, including:</p>
<ol>
<li><p><strong>Reduce sort volume:</strong>  Similar to the best practices above, this involves using the WHERE clause to filter out results as early as possible to reduce the number of sorted rows.</p>
</li>
<li><p><strong>Use a LIMIT:</strong>  As we can see above, a LIMIT clause is pushed down into the query, eliminating spilling to storage with a huge improvement in Snowflake query performance.</p>
</li>
<li><p><strong>Scale Up:</strong> The diagram below illustrates the internal structure of a MEDIUM-size warehouse, which includes four servers**.**  By scaling up to a larger warehouse, we can spread the workload across multiple servers, which gives (in this case) four times the memory and SSD, which is the simplest way to resolve the issue.</p>
</li>
<li><p><strong>Cluster the Data:</strong>  A final (although sometimes challenging) approach involves clustering the data by the sort key.  This often eliminates the SORT operation and can have a massive impact on query performance.</p>
</li>
</ol>
<h2 id="heading-clustering-the-data">Clustering the Data</h2>
<p>The quickest and most simple way of clustering data is to sort it by one or more columns.  The SQL snippet below will produce a sorted version of a table:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> overwrite <span class="hljs-keyword">into</span> orders
<span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> orders
<span class="hljs-keyword">order</span> <span class="hljs-keyword">by</span> o_orderdate;
</code></pre>
<p>The above query replaces the contents of the ORDERS table with data sorted by ORDER DATE, which means any GROUP BY or ORDER BY won’t need to sort the data.  This approach is, however, not without its drawbacks, and it’s worth reading the article <a target="_blank" href="https://www.analytics.today/blog/snowflake-clustering-best-practice">Snowflake Clustering Keys Best Practice</a> for further guidance.</p>
<h2 id="heading-maximizing-snowflake-data-transformation-performance">Maximizing Snowflake Data Transformation Performance</h2>
<p>Data Transformation involves fetching, cleaning, merging, and transforming data into a form suitable for end-user consumption, and this often accounts for 60-80% of the overall system cost.  It, therefore, must be the primary focus for Snowflake query tuning.  In addition to producing results faster, tuning transformation jobs can significantly impact Snowflake's cost.</p>
<h2 id="heading-avoid-row-by-row-processing">Avoid row-by-row-processing</h2>
<p>Data Engineers and Data Scientists have the option to execute procedural code against Snowflake using Python, Java, Javascript and Snowflake Scripting in addition to Scala using Snowpark. There's a risk however, that coding in a language which supports LOOPS, leads to repeated single-row query execution - also know as "Row-by-Row" processing.</p>
<blockquote>
<p>Row by Row Processing - is "Slow-by-Slow" - <a target="_blank" href="https://asktom.oracle.com/Misc/slow-by-slow.html">Tom Kyte</a></p>
</blockquote>
<p>One of the most important query-tuning best practices on Snowflake is to avoid row-by-row processing.  Unlike on-premises databases like Oracle, Snowflake is designed primarily for set-at-a-time processing of large data volumes rather than single-row inserts, updates, or deletes.</p>
<p>Take the following row-by-row solution, which takes around ten seconds to copy just ten rows into the CUSTOMER table:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">declare</span>
v_counter <span class="hljs-built_in">number</span>;
<span class="hljs-keyword">begin</span>
  <span class="hljs-keyword">for</span> v_counter <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> <span class="hljs-keyword">to</span> <span class="hljs-number">10</span>, <span class="hljs-keyword">do</span>
     <span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> customer
     <span class="hljs-keyword">select</span> *
     <span class="hljs-keyword">from</span> snowflake_sample_data.tpcds_sf100tcl.customer
     <span class="hljs-keyword">limit</span> <span class="hljs-number">1</span>;
  <span class="hljs-keyword">end</span> <span class="hljs-keyword">for</span>;
<span class="hljs-keyword">end</span>;
</code></pre>
<p>Then, consider the following set-at-a-time query that copies data from the same table in 9.4 seconds on an XSMALL warehouse.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">insert</span> <span class="hljs-keyword">into</span> customer
<span class="hljs-keyword">select</span> *
<span class="hljs-keyword">from</span> snowflake_sample_data.tpcds_sf100tcl.customer
<span class="hljs-keyword">limit</span> <span class="hljs-number">15000000</span>;
</code></pre>
<p>In conclusion, using set-at-a-time queries, Snowflake can process fifteen million rows simultaneously as row-by-row processing copies ten rows.  That’s a performance improvement of 1.5 million times.</p>
<p>The only exception to the above scenario is when dealing with Snowflake Hybrid Tables, designed for OLTP-type applications processing single-row DML operations in milliseconds.</p>
<h2 id="heading-scale-up-for-larger-data-volume">Scale up for larger Data Volume.</h2>
<p>This best practice is true for almost any end-user or transformation queries and involves executing long-running queries on a larger virtual warehouse.</p>
<p>In principle, provided the query workload can be distributed across all the available servers, any query will run twice as fast on the next warehouse size.  Consider the following table showing the benchmark results of copying a 1.3 TB table on different warehouse sizes.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/09622cd1-d387-49db-bc7e-be4c4199c11e.png" alt class="image--center mx-auto" /></p>
<p>The results above demonstrate very large data volumes can be scaled from an XSMALL warehouse running for four hours to an X6LARGE in just 60 seconds.  Notice the improvement is around 76% to 100% each time.  This is the most important key performance indicator (KPI) when warehouse sizing.  Provided the workload completes around twice as fast each time, it’s worth trying the workload on the next size up.</p>
<p>The challenge of identifying the optimum warehouse size is illustrated in the diagram below.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/5135263c-472f-4f7d-abb4-3091ba638f78.png" alt class="image--center mx-auto" /></p>
<p>The above diagram shows the performance of a benchmark query executed on an XSMALL to X2LARGE warehouse.  In this case, the query processed a relatively small data volume (several gigabytes), and although each time we scaled up to a larger warehouse, (for example from an XSMALL to a SMALL), the query was executed twice as fast.</p>
<p>Since the charge rate per second doubles with warehouse size, we can conclude that each step where the performance is at least double, that the cost will remain the same.</p>
<blockquote>
<p>Snowflake has an amazing super-power. You can often get the same work done twice as fast for the same cost. - <a target="_blank" href="https://kentgraziano.com/snowflake-resources/">Kent Graziano</a> (The Data Warrior)</p>
</blockquote>
<p>However, each time the performance gain is less than 100%, it costs slightly more, although of course you get the extra performance improvement.</p>
<p>For example, running the query on an XLARGE warehouse would cost 12% more than a LARGE warehouse for an 88% performance improvement.</p>
<p>The real insight here, however, is that the query time is reduced from 80 minutes on an XSMALL warehouse to just 8 minutes on a LARGE for the same cost.</p>
<p>Be aware though, there's almost no performance benefit in scaling up relatively simple, short running queries. The best approach is to execute your workload (all the queries for a given job or set of dashboard users), on a warehouse size, and then scale up until the performance improvement is less than 100%.</p>
<h2 id="heading-maximizing-snowflake-data-loading-performance">Maximizing Snowflake Data Loading Performance</h2>
<p>One of the single biggest mistakes made by data engineers is assuming a COPY operation will execute faster on a bigger virtual warehouse.  The correct answer is, yes, it will, but it depends.</p>
<p>If you execute the following SQL to load data files from the @SALES stage, Snowflake will use the currently assigned virtual warehouse to load data into the SALES table.  Let’s assume you use a MEDIUM-size warehouse to maximize load performance.</p>
<pre><code class="lang-sql">copy into sales
from @sales_stage;
</code></pre>
<p>If you’ve only a single file to load, the diagram below illustrates how Snowflake executes the COPY operation using a single CPU.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/7ac58bf0-c764-4720-bc48-0397313acba9.png" alt class="image--center mx-auto" /></p>
<p>In summary, this won’t improve COPY performance and will take the same time to load on a MEDIUM-size warehouse as an XSMALL.</p>
<p>If you deliver hundreds of files, each file will be loaded in parallel on a separate CPU core with massive load performance.  As a MEDIUM size warehouse has four servers, each with eight CPU cores, you can load up to 32 files in parallel, effectively improving load performance by 3,200%.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/e35a9e8b-6693-425f-b0fa-55a96c928581.png" alt class="image--center mx-auto" /></p>
<p>Be aware, however, it’s best practice to ensure data files are sized between 100-250MB, which means you’ll need a huge volume of data to justify splitting files.  It’s, therefore, good practice to use just two warehouses to load all data into Snowflake.   One XSMALL warehouse for single files (data loads of up to 250MB compressed), and another MEDIUM or larger warehouse for huge data loads split into file chunks of up to 250MB.</p>
<p>Remember, an XSMALL warehouse can load just eight files in parallel; during very busy times, you may be loading more than eight files in parallel.  It’s, therefore, also a best practice to configure data-loading warehouses to use the Snowflake scale-out feature.  The SQL statement below illustrates how:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">create</span> warehouse load_vwh <span class="hljs-keyword">with</span>
   Warehouse_size = XSMALL
   min_cluster_count = <span class="hljs-number">1</span>
   max_cluster_count = <span class="hljs-number">8</span>
   auto_suspend = <span class="hljs-number">30</span>;
</code></pre>
<p>The diagram below illustrates how the solution works.  It shows how multiple parallel COPY operations are executed on a single XSMALL warehouse.  As the number of operations reaches eight parallel loads, Snowflake automatically adds additional servers to cope with the additional workload.</p>
<p><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/ee651d0d-e65c-4e78-9c53-2799e5dacef0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, Snowflake deploys a revolutionary hardware and software architecture to maximize query performance, supporting scaling up (to a larger warehouse) and out (for more concurrent queries). Using the simple query performance strategies outlined in this article can greatly impact overall query performance, often for very little effort.</p>
<hr />
<p>Deliver more performance and cost savings with Altimate AI's cutting-edge AI teammates. These intelligent teammates come pre-loaded with the insights discussed in this article, enabling you to implement our recommendations across millions of queries and tables effortlessly. Ready to see it in action? Request a recorded demo by just sending a chat message (<a target="_blank" href="https://app.myaltimate.com/contactus">here</a>) and discover how AI teammates can transform your data teams.</p>
<p><a target="_blank" href="https://app.myaltimate.com/contactus"><img src="/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/d9ad5daf-6edc-4c94-a697-80f6cb79cbc5.png" alt /></a></p>]]></content:encoded>
    <enclosure url="https://altimate.ai/blog/optimizing-snowflake-queries-expert-strategies-for-data-engineers-and-analysts/3bc6e31d-4dc7-49e5-9e4e-cc8cadce929c.png" type="image/png" />
  </item>
</channel>
</rss>
