<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Altimate.ai | Data Engineering Blog]]></title><description><![CDATA[A technical blog by the Altimate AI team, building the leading agentic harness for data engineering teams.]]></description><link>https://blog.altimate.ai</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1705472486447/Kxc4gLGzC.png</url><title>Altimate.ai | Data Engineering Blog</title><link>https://blog.altimate.ai</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 13:16:43 GMT</lastBuildDate><atom:link href="https://blog.altimate.ai/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Databricks Serverless vs Classic Compute: Which One Is Actually Cheaper?]]></title><description><![CDATA[Whenever somebody mentions serverless, two things come to mind: it should be cheaper than normal resources and no infrastructure management, right? This is certainly what has been claimed both from Da]]></description><link>https://blog.altimate.ai/databricks-serverless-vs-classic-compute-which-one-is-actually-cheaper</link><guid isPermaLink="true">https://blog.altimate.ai/databricks-serverless-vs-classic-compute-which-one-is-actually-cheaper</guid><category><![CDATA[databricks cost]]></category><category><![CDATA[databricks serverless]]></category><category><![CDATA[databricks compute]]></category><category><![CDATA[Databricks]]></category><dc:creator><![CDATA[Saurabh Arora]]></dc:creator><pubDate>Fri, 04 Sep 2026 15:02:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/631080dd75af73ad1f063c47/e6fa6181-3a1f-497e-9337-823e235c66da.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Whenever somebody mentions <em>serverless</em>, two things come to mind: it should be cheaper than normal resources and no infrastructure management, right? This is certainly what has been claimed both from Databricks and from several (potentially sponsored) case studies.</p>
<p>But it is still a very debatable topic.</p>
<p>In this blog post, I will be dissecting <strong>Databricks Serverless</strong>, which was initially introduced in 2017 for Apache Spark. Today, almost every offering in Databricks has its serverless option, and this hosting option has gained quite a bit of interest.</p>
<p>So, let’s look at:</p>
<ul>
<li><p>What Databricks Serverless is, exactly</p>
</li>
<li><p>Compare Databricks Serverless costs to Databricks classic compute</p>
</li>
<li><p>Under which circumstances should you pick one over the other</p>
</li>
</ul>
<p>But first, let’s talk first about serverless in general.</p>
<h2>What is Serverless Compute? And Why Might You Use It?</h2>
<p>In simple terms, the concept of serverless compute is that you run your workloads on third-party infrastructure without having to manage anything by yourself; the managed service does the heavy lifting.</p>
<p>Think of it as using a flexible, on-demand service: you use it for the exact time you need and pay only for that period, without having to maintain hardware or handle backend upkeep costs.</p>
<p>Just like any on-demand service, there are fair-use rules and boundaries. The provider guarantees fast availability and manages the capacity behind the scenes, but there are operational limits in place.</p>
<p>Databricks provides multiple types of serverless compute. Below are the key serverless compute types:</p>
<ul>
<li><p><strong>Serverless SQL Warehouses</strong>: On-demand elastic compute for running SQL queries from the SQL editor, dashboards, and BI tools. Warehouses start in seconds and scale automatically with demand, so there's no sizing decision and no idle cluster sitting around. Billed per DBU-second on its own serverless SQL SKU.</p>
</li>
<li><p><strong>Serverless All Purpose Compute:</strong> This serverless compute removes the need to manage the underlying cluster infrastructure, while automatically scaling compute resources based on workload demand. It is good for interactive development, notebooks, and ad hoc analysis where faster startup and less cluster management matter more than minimizing compute cost.</p>
</li>
<li><p><strong>Serverless Jobs Compute</strong> Compute for scheduled and triggered jobs (what used to be Workflows). Databricks provisions compute for every run and scales it to match the workload, with smart retries and cloud failover built in. It supports notebook, Python script, dbt, Python wheel, and JAR tasks. With serverless Jobs Compute, Photon and autoscaling are always on.</p>
</li>
<li><p><strong>Serverless Spark Declarative Pipelines:</strong> The compute behind Lakeflow Spark Declarative Pipelines. You define the transformation logic and Databricks runs the pipeline without you configuring or deploying any infrastructure. It’s a good fit for streaming and incremental ETL where cluster sizing is hard to predict.</p>
</li>
<li><p><strong>Serverless GPU compute:</strong> Still in beta and aimed at deep learning: training and fine-tuning custom models without managing GPU fleets or drivers. It runs on A10s for smaller work and H100s (8 GPUs per node) for large interactive or distributed training.</p>
</li>
</ul>
<h2>Standard vs. Performance-Optimized vs. Serverless Compute</h2>
<p>Let’s compare three things:</p>
<ul>
<li><p><strong>Standard Databricks Compute</strong> whereby we mean any instance type with minimal effort on performance optimization.</p>
</li>
<li><p><strong>Performance-optimized compute</strong> refers to instance family and configuration, which is suited for the kind of workload you want to run; (e.g. a scheduled long-running job that runs every Monday morning)</p>
</li>
<li><p><strong>Serverless compute</strong>, where you don’t need to think about what instance family or thing you’re using.</p>
</li>
</ul>
<p>Here's how the three stack up.</p>
<table>
<thead>
<tr>
<th></th>
<th>Standard (classic)</th>
<th>Performance-optimized (classic)</th>
<th>Serverless</th>
</tr>
</thead>
<tbody><tr>
<td>Best fit for</td>
<td>Anything where nobody has looked at the bill yet</td>
<td>Steady, predictable jobs whose shape you already know</td>
<td>Bursty, unpredictable, or interactive work</td>
</tr>
<tr>
<td>What you configure</td>
<td>A generic instance type and cluster size</td>
<td>Instance family, node type, and autoscale range chosen for the workload</td>
<td>Nothing. Databricks chooses and scales it per run</td>
</tr>
<tr>
<td>Startup time</td>
<td>Minutes per cluster start (zero once running, billed while idle)</td>
<td>Minutes, same as standard</td>
<td>Seconds</td>
</tr>
<tr>
<td>Billed for</td>
<td>DBUs plus the underlying cloud VM, for however long the cluster is up</td>
<td>Same as Standard, but sized to cut waste</td>
<td>DBUs only, at a higher per-DBU rate, for the seconds the job actually runs</td>
</tr>
<tr>
<td>Who tunes it</td>
<td>You, once, when the cluster policy is set</td>
<td>You, per workload, based on profiling the job</td>
<td>Databricks, automatically, on every run</td>
</tr>
</tbody></table>
<h2>Should you use Databricks Serverless Compute?</h2>
<p>There are two main reasons to choose serverless.</p>
<p>First, you eliminate routine maintenance or the need to provision capacity up front, so your team focuses on building pipelines instead of managing machines.</p>
<p>Second, resources start in seconds instead of minutes, which removes long wait times and stops you from paying for idle compute.</p>
<p>Serverless tends to be the right call when:</p>
<ul>
<li><p>You want zero cluster management: no configs to write, no sizing to tune, and a startup measured in seconds rather than minutes.</p>
</li>
<li><p>The workload is spiky, interactive, or unpredictable, such as ad hoc SQL, BI dashboards, notebooks, or short jobs.</p>
</li>
<li><p>You are paying for idle time on classic clusters today and want to get rid of it.</p>
</li>
<li><p>Iteration speed matters more to you than fine-grained cost control.</p>
</li>
</ul>
<p><a href="https://blog.altimate.ai/understanding-databricks-compute-costs">Cost-wise</a>, Databricks serverless carries a higher per-DBU rate than classic compute, but you only pay for the seconds a job actually runs. Classic is cheaper per DBU, but you pay for however long the cluster stays up, idle time, and carry cloud VM costs separately. Utilization is what tips the balance, not the list price of either one.</p>
<p>During our benchmarking, serverless compute didn’t require much cluster-management work and delivered the shortest runtime. However, the trade-off here is price: after applying a 6% effective-rate discount, the serverless run costs <strong>$8.90</strong>, vs <strong>$3.33</strong> for the least-expensive on-demand configuration and <strong>$2.32</strong> for the least-expensive spot configuration which is a <strong>2.7x</strong> and <strong>3.8x</strong> premium, respectively.</p>
<img src="https://cdn.hashnode.com/uploads/covers/631080dd75af73ad1f063c47/5c3ed8b1-3aa5-4dfa-9057-544ba41ce53d.png" alt="Cost per TPC-DS run" style="display:block;margin:0 auto" />

<h2>Benchmark setup</h2>
<p>Below is benchmark setup we used in our comparison:</p>
<ul>
<li><p><strong>Workload:</strong> TPC-DS at scale factor 1,000 - approximately a 1 TB decision-support dataset under the <a href="https://www.tpc.org/tpc_documents_current_versions/pdf/tpc-ds_v1.4.0.pdf">TPC scaling model</a>.</p>
</li>
<li><p><strong>Serverless:</strong> default platform settings.</p>
</li>
<li><p><strong>Classic compute:</strong> <code>m6id.xlarge</code>, <code>c5d.xlarge</code>, and <code>r6id.xlarge</code> workers, each tested with on-demand and spot capacity.</p>
</li>
<li><p><strong>Cluster policy:</strong> autoscaling from 4 to 12 workers; <code>m6id.large</code> on-demand driver; Databricks Runtime 14.3 LTS with Spark 3.5.0.</p>
</li>
<li><p><strong>Sampling:</strong> three paired runs per day 06:00, 14:00, and 22:00 for 21 days, giving 63 observations per worker type. Serverless and classic jobs were launched concurrently to reduce time-of-day bias.</p>
</li>
<li><p><strong>Primary measures:</strong> effective cost per successful run and end-to-end elapsed time. Runs should use the same region, table snapshot, file layout, query set, and cache policy; retries and spot reclamations belong in the cost of the completed run.</p>
</li>
</ul>
<p>One thing to note here, two of the compute models require different accounting.</p>
<p>For classic compute, integrate driver and worker uptime across autoscaling events, then add both infrastructure and DBU charges:</p>
<p><code>classic cost = Σ(worker-seconds × [VM rate + DBU rate]) + driver + storage + retry overhead</code></p>
<p>For serverless, we used metered DBUs at the effective contracted rate. Because Databricks selects the worker shape and scaling policy, this is a platform-mode comparison rather than an instance-for-instance test. <strong>Default serverless settings may also differ in Photon use and execution-engine behavior, so query plans and cache state should be checked before attributing the runtime gap solely to elasticity</strong>.</p>
<h2>Results</h2>
<img src="https://cdn.hashnode.com/uploads/covers/631080dd75af73ad1f063c47/ddd13845-855a-4c9a-9eb3-327ce913cf6d.png" alt="Average runtime by compute option" style="display:block;margin:0 auto" />

<p>Serverless finishes about <strong>5 minutes sooner than on-demand</strong> and <strong>21 minutes sooner than spot</strong>, but the additional spend is <strong>$5.57</strong> and <strong>$6.58</strong> per run compared with the cheapest option in each class. Put differently, the cost premium is roughly <strong>$1.11 in additional cost per minute saved</strong> vs on-demand and <strong>$0.31 per minute saved</strong> vs spot.</p>
<p>For latency-sensitive pipelines, that premium may be justified by tighter completion windows, faster scale-up, and lower operational load. For scheduled workloads with slack in the service-level objective, classic compute remains the stronger cost choice, particularly when worker families, Photon, shuffle storage, and autoscaling bounds are tuned to the query mix. The decision should therefore be made against the value of a minute saved, not cost or runtime in isolation.</p>
<p><a href="https://qubika.com/blog/databricks-cost-series-part-2-serverless-vs-classic/">Qubika</a> reports the same job swinging from 30% cheaper to 2x more expensive on serverless depending on the workload, and their conclusion is to benchmark your own jobs rather than trust a fixed ratio either way.</p>
<p>There is no fixed answer here, it depends on how long and how often your job runs.</p>
<p>Serverless removes startup and idle overhead, which dominates short jobs. A 4-minute job that previously consumed 12 minutes of cluster time now consumes 4. The longer the job runs, the smaller that overhead becomes as a share of the total, and classic compute's lower per-DBU rate starts to win on its own.</p>
<p>The rough break-even is around 30 minutes of runtime. Below that, serverless is usually cheaper before you even account for the operational savings. Above that, classic wins unless serverless is delivering a 30 to 60% speedup that classic cannot match.</p>
<p>That provides you three ways to decide what to go for once you know a job's typical run duration and how steady its schedule is:</p>
<ul>
<li><p><strong>Choose serverless</strong> for jobs that run under 30 minutes; if the schedule is unpredictable or interactive, such as ad hoc SQL or BI dashboards, and you don’t want infrastructure management, no cluster spin, and no separate bill for cloud resource usage.</p>
</li>
<li><p><strong>Choose Classic</strong> for jobs that run long and steady, where you can size the cluster once and push the cost down further with spot instances or committed-use discounts, finer control over the cost. Additional observability is required into what is going on with the resources and debugging and monitoring.</p>
</li>
<li><p><strong>Run a hybrid</strong> where most shops end up: serverless for ad hoc and interactive work and classic job clusters for the long, predictable ETL that runs the same way every night.</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/6d113282-a7f0-45f2-a9c2-40ab5af7bff5.svg" alt="" style="display:block;margin:0 auto" />

<h2>When to Keep Classic Databricks Compute</h2>
<p>As discussed above, classic compute can be optimized to a certain extent (e.g. spot instances, committed-use discounts, right-sizing the cluster once) but it remains the better choice outright in a few concrete situations:</p>
<ul>
<li><p>You need custom configuration, such as a specific instance type, GPUs, init scripts, OS-level libraries, or nonstandard Spark configs.</p>
</li>
<li><p>The workload is long-running and steady, which means you can use spot instances or reserved and committed-use discounts to push the cost well below what serverless would charge for the same hours.</p>
</li>
<li><p>You have strict networking requirements, such as a workload that has to run inside your own VPC or VNet.</p>
</li>
<li><p>You are running heavy ML training or another specialized workload that serverless does not fully support yet; (Databrick’s serverless GPU offering is in beta as of now).</p>
</li>
</ul>
<h2>Conclusion</h2>
<p>Neither Databricks compute option is cheap in every case. But your decision should be based on the same thing in every job: how long it runs and how steady its schedule is. So pull up your own longest-running and shortest-running jobs; check where they fall against the 30-minute line, and you should have a better answer to your situation. Decide what to use if your workloads are predictable or bursty analytics BI dashboards, like dashboards that refresh once a week or when someone opens them up.</p>
]]></content:encoded></item><item><title><![CDATA[Understanding Databricks Compute Costs]]></title><description><![CDATA[There is so much around Databricks cost optimization techniques, strategies, approaches, what to do, what not to do, and many guides from authors, even official sources from Databricks. All of those c]]></description><link>https://blog.altimate.ai/understanding-databricks-compute-costs</link><guid isPermaLink="true">https://blog.altimate.ai/understanding-databricks-compute-costs</guid><category><![CDATA[Databricks]]></category><category><![CDATA[altimateAI]]></category><category><![CDATA[finops]]></category><dc:creator><![CDATA[Saurabh Arora]]></dc:creator><pubDate>Wed, 19 Aug 2026 14:06:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/99cb0dd4-1cf6-4536-81c5-ce9954e222f8.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There is so much around Databricks cost optimization techniques, strategies, approaches, what to do, what not to do, and many guides from authors, even official sources from Databricks. All of those converge on the same checklist: turn on auto-termination; use job clusters; try spot instances; enable Photon...</p>
<p>None of that is wrong. The problem is that it assumes you already know where your money is going, and most teams don't.</p>
<p>We still need to make sense of how Databricks compute actually works. What decides your Databricks bill when you get billed for the usage in a month? Though it sounds easier if we just say, "Hey, you’ve used 300 DBU, and the DBU rate is $0.40 per hour. That basically means 300 DBU times $0.40 = $120, right?"</p>
<p>But then you might be wondering about that DBU 300; is that the only cost you need to take into account? What did it cost to keep the compute running that consumed those DBUs? And if someone asked you what the marketing team's dashboards cost last month, or how much of that was compute sitting idle, could you answer?</p>
<p>These are all the questions I’m going to answer in this blog post, from types of compute to how you’re getting billed, later looking into how to achieve visibility of compute usage to make better decisions for your organization. Let’s start with understanding compute!</p>
<h2>How Databricks Bills Compute</h2>
<p>Databricks emerged from a real architectural frustration. For years, organizations paid twice for analytics. First, they stored data in one place, usually in relatively cheap object storage. Then they copied that same data into a second, more expensive system so it could be queried efficiently. The movement between those layers was not easy and costly. It was a recurring double cost on every insight.</p>
<p>The Lakehouse model helped change this equation. Instead of storing data once and copying it into a separate warehouse for analysis, the idea was to store data once in <a href="https://opendataformats.org/">open formats</a> and bring compute engines to that data. That is one of the core economic principles behind the Databricks model.</p>
<p>To understand how this affects your Databricks billing, see how Databricks decouples three core layers:</p>
<ol>
<li><p>Storage: Holds the data indefinitely in open formats at raw cloud storage rates.</p>
</li>
<li><p>Governance: Controls access and security across the entire data estate via Unity Catalog.</p>
</li>
<li><p>Compute: Executes work against the stored data on demand.</p>
</li>
</ol>
<h3>The Databricks Compute layer</h3>
<p>Databricks compute is the execution layer. It is where queries run, notebooks execute, jobs transform data, and machine learning workflows consume governed datasets and turn them into outputs. In the Databricks operating model, storage preserves data and governance defines who can use it, but compute is where value is actually created.</p>
<h4>Databricks Compute types</h4>
<p>Databricks offers three types of compute:</p>
<ul>
<li><p><strong>Serverless Compute</strong>: Fully managed, instantly available compute where Databricks handles cluster provisioning, scaling, and maintenance.</p>
</li>
<li><p><strong>Classic Compute</strong>: Compute clusters provisioned directly in your cloud account, giving you full control over node types and configurations.</p>
</li>
<li><p><strong>SQL Warehouses</strong>: Specialized compute optimized specifically for SQL queries, BI dashboards, and data warehousing workloads.</p>
</li>
</ul>
<p>When storage and compute are separated, their costs do not disappear; rather, they become visible, more distributed, and more operational. Since these layers are separated the total Databricks cost becomes a <strong>two-bill problem</strong>.</p>
<p>The first bill is <strong>platform cost,</strong> where you pay for the Databricks platform in DBUs.</p>
<p>A DBU, or <em>Databricks Unit</em>, is Databricks’ billing unit for compute consumption. It measures compute power consumed over time, and your bill is tracked by compute SKU, usage type, and workload category rather than as a single flat "cluster cost". For example, in mid-2026 an all-purpose compute cluster typically costs around $0.55 per DBU-hour for a standard runtime.</p>
<p>The second bill comes from <strong>your cloud provider</strong>, where you pay for the infrastructure cost: virtual machines, disks, and associated network costs. However, there is one major exception in the case of serverless compute, whose virtual machine cost is included in the Databricks DBU charge already, because it is managed by Databricks itself.</p>
<p>Now, let’s go back to that $120 calculation from the intro; we know now that $120 is not the whole picture of total cost. DBUs are the Databricks half. The EC2 or VM hours, the disks, the NAT gateway, and the cross-zone traffic: all of these usage costs arrive on a separate invoice, which you don’t see on the Databricks console. This split is why two common cost conversations go sideways:</p>
<ol>
<li><p>A team cuts DBUs by 20% and wonders why the total bill barely moved. The infrastructure half didn't change.</p>
</li>
<li><p>A team compares the serverless DBU rate against the classic DBU rate and concludes serverless costs several times more. But serverless includes the VM whereas Classic doesn't.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/5f4fc6af-b568-45f6-9a22-987990f81280.png" alt="Diagram titled &quot;Solving the two-bill problem,&quot; contrasting the traditional split of a Databricks invoice for DBUs plus a separate cloud provider invoice for VMs, disks, and networking against the serverless exception, where infrastructure costs are bundled into one consolidated DBU invoice." style="display:block;margin:0 auto" />

<p>So the right question is not "What is our DBU spend?" It is how much compute you consumed, and what infrastructure you had to keep running to consume it.</p>
<h2>Start with system tables (and know their gaps)</h2>
<p>To understand usages, Databricks system tables are the right place to start, and most teams underuse them. Four tables matter most for compute cost, plus one more if you run SQL warehouses:</p>
<table>
<thead>
<tr>
<th>Table</th>
<th>What it gives you</th>
</tr>
</thead>
<tbody><tr>
<td><code>system.billing.usage</code></td>
<td>DBU quantities, SKU names, and a <code>usage_metadata</code> struct with <code>cluster_id</code>, <code>warehouse_id</code>, <code>job_id</code>, and <code>job_run_id</code>, plus custom tags and the identity that ran the workload</td>
</tr>
<tr>
<td><code>system.billing.list_prices</code></td>
<td>List prices per SKU over time, so you can turn DBUs into dollars</td>
</tr>
<tr>
<td><code>system.compute.clusters</code></td>
<td>Cluster configuration history, so you see what a cluster looked like when it ran</td>
</tr>
<tr>
<td><code>system.compute.node_timeline</code></td>
<td>Per-minute CPU and memory per node.</td>
</tr>
</tbody></table>
<p>Add <code>system.query.history</code> if you run SQL warehouses, because it records how long queries spent waiting for compute.</p>
<p>Before writing anything custom, you can import Databricks' <a href="https://docs.databricks.com/aws/en/admin/system-tables/jobs-cost">Lakeflow observability dashboard</a>. It ships as JSON you drop into your workspace, and the page publishes the SQL behind every tile. Most teams learn more in an hour with it than a week of writing their own queries.</p>
<p>Note - if you use the Lakeflow observability dashboard, be aware that <code>usage_metadata.job_id</code> is only populated for jobs on job compute or serverless. So filtering billing usage for an all-purpose SKU where <code>job_id</code> is not null returns nothing at all. The empty result only means the filter never had rows to match. To actually find jobs running on all-purpose clusters, you have to go through <code>job_task_run_timeline</code> joined against <code>compute.clusters</code>, and Databricks <a href="https://docs.databricks.com/aws/en/admin/system-tables/jobs">publishes that query</a>.</p>
<p>One thing you will notice is <em>none of these tables contain a single dollar of cloud infrastructure cost</em>. To get a total bill, you join Databricks usage against your cloud provider's cost and usage report based on resource tags. Databricks does propagate cluster tags.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/76a18c3c-79d5-44cd-bcad-04ef6e4e7c87.png" alt="Altimate AI Current State view of Databricks costs for Jul 6 to Aug 3, 2026, totaling $49.51K, broken into SQL Warehouse $22.27K, Clusters $20.95K, Lakehouse $3.36K, AI/ML $2.12K, and Platform $801, shown as a daily stacked bar chart of spend by SKU type." style="display:block;margin:0 auto" />

<p><em>Altimate's Clusters and SQL Warehouses views stitch both halves together and attribute the result down to cluster, warehouse, job, and team, so you can even read one number per workload instead of reconciling two exports by hand.</em></p>
<h2>Where your compute money goes</h2>
<p>Once you start thinking in terms of two bills, the next step is understanding what usually drives the cost. For most teams, compute money goes into a familiar set of buckets:</p>
<table>
<thead>
<tr>
<th>Where the money goes</th>
<th>Which bill it contributes to</th>
<th>What to look at first</th>
</tr>
</thead>
<tbody><tr>
<td>Idle time on interactive compute</td>
<td>Both</td>
<td>Cluster uptime against query time</td>
</tr>
<tr>
<td>The wrong compute type for the workload</td>
<td>Databricks (DBU)</td>
<td>All-purpose SKUs running scheduled jobs</td>
</tr>
<tr>
<td>Oversizing</td>
<td>Both</td>
<td>Node utilization in system.compute.node_timeline</td>
</tr>
<tr>
<td>Loose or poorly bounded autoscaling</td>
<td>Both</td>
<td>The minimum you always pay, and how long max is held</td>
</tr>
<tr>
<td>Long-running interactive resources that nobody turns off</td>
<td>Both</td>
<td>Auto-termination settings</td>
</tr>
<tr>
<td>Streaming patterns that run 24*7 when the business requirement does not actually need 24*7 freshness</td>
<td>Both</td>
<td>Trigger mode against the business requirement</td>
</tr>
<tr>
<td>Infrastructure side effects such as networking, egress, or duplicated data movement</td>
<td>Cloud only</td>
<td>Your cloud cost and usage report, by tag</td>
</tr>
</tbody></table>
<p>Workloads drift, though, so the table above is worth revisiting on a regular schedule rather than only after a bill shock prompts a one-time sprint.</p>
<p>Sometimes despite all the efforts, a pipeline can be on the wrong SKU, oversized, and idle half the time all at once, and it will look completely healthy on every alert you have unless you have visibility at that granular level.</p>
<h3>When Serverless Helps, and When It Doesn't</h3>
<p>As we discussed earlier, serverless compute is good for bursty workloads such as BI workloads, which often come in bursts: a user refreshes a dashboard, runs a query, inspects results, then goes idle. In non-serverless warehouses, startup time is long enough that teams often leave resources running to avoid waiting. Serverless can help change this trade-off because it can start and scales in seconds and can terminate idle compute sooner than all-purpose/classic compute.</p>
<p>What you give up is control. No picking instance families, no spot strategy, no pool tuning. That's fine when your problem is startup delay and idle waste. It hurts when your problem needs precise control over the infrastructure underneath the workload.</p>
<p>So skip "is serverless cheaper?" and ask "what kind of waste are we trying to eliminate?" If the waste comes from slow startups, bursty access, and long idle windows, serverless often is the best choice at its premium price.</p>
<p>If the workload is steady, predictable, and suited to deliberate sizing and cloud cost engineering, classic compute can be more cost effective. That is especially true when teams know enough about their workload shape to right-size aggressively and use cloud primitives that serverless does not expose in the same way.</p>
<p>This is also why visibility comes before optimization. Without data on burstiness, concurrency, and idle windows, the serverless debate turns ideological instead of operational.</p>
<h3>Idle and the Wrong Compute Type</h3>
<p>These two problems compound each other. Take a big all-purpose cluster: the work finishes fast because the instance is large, but the cluster hangs around afterward because spinning it back up is slow. You're paying double: a costlier instance, and longer idle time on top of it. All-purpose clusters are also much easier to leave running between interactions than job compute, which only runs while there's a job to run.</p>
<p>Databricks’ <a href="https://www.databricks.com/blog/chaos-control-cost-maturity-journey-databricks">cost maturity post</a> puts it as "Job compute is typically 2-3x cheaper than all-purpose." Treat that as a starting range rather than a rule, because what you actually save depends on how much of the runtime was idle and on which half of the bill dominates for that workload. This sounds like nobody would miss this detail; however, teams do miss it constantly, and the pattern is always the same:</p>
<ol>
<li><p>A notebook starts on an all-purpose cluster because development is interactive.</p>
</li>
<li><p>The workflow proves useful.</p>
</li>
<li><p>It becomes production-critical.</p>
</li>
<li><p>Nobody revisits the compute type.</p>
</li>
<li><p>The company pays a production bill for a development pattern.</p>
</li>
</ol>
<p>A quick fix to this is auto-termination: configuring it for all interactive compute resources, and scheduled restart patterns for business-hour usage where startup delay matters. It controls idle waste, but it does not fix the underlying pattern if the workload is living on the wrong compute type in the first place.</p>
<p>It is one thing to tell every team "use job compute." It is more useful to know exactly which production pipelines are still running on all-purpose clusters, how long those clusters sit idle, and what the cost delta looks like, which is what the `system.billing.usage` and `compute.node_timeline` join from the previous section is for.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/1cab7cec-a84b-4957-91bb-3287c9ddfebb.png" alt="Altimate AI Discover page for Jul 4 to Aug 3, 2026, showing $714–$742 in money savings, 3.8 hours of time savings, and 66 opportunities, above a table of opportunities such as continuous jobs running on an interactive cluster, each with resource details, savings estimates, effort rating, and assigned owner." style="display:block;margin:0 auto" />

<p><em>The Discover page overview in</em> <a href="https://altimate.ai"><em>Altimate.ai</em></a> <em>Enterprise platform surfaces exactly this kind of opportunity.</em></p>
<p><a href="https://altimate.ai">Altimate.ai</a> enterprise platform provides this visibility from the discover page, which we just talked about. You see an opportunity where a continuous job is running on an interactive cluster, which can be switched to a serverless job or job cluster rather than running on an interactive cluster. For more information see <a href="https://help.altimate.ai/platform/discover-savings/explore/">Altimate.ai enterprise platform docs</a></p>
<h3>Spot and Fleet Instances</h3>
<p>On classic compute, spot is still the most underused lever. Use spot instances for workloads that can tolerate interruptions with an important guardrail: the first instance, the Spark driver, should stay on demand while workers use spot capacity. Keep the Fleet instance types on AWS, where Databricks can choose the best-matching physical instance types by price and availability. See more in Databricks' <a href="https://docs.databricks.com/aws/en/lakehouse-architecture/cost-optimization/best-practices">guidance on choosing optimal resources</a>.</p>
<p>However, Spot is not a universal answer. It works best when the workload is fault-tolerant and when retry, checkpointing, or restart behavior makes interruption acceptable. Batch ETL, retry-friendly pipelines, and some model-training jobs are natural candidates. Low-latency or interruption-sensitive workloads are not.</p>
<p>Spot only touches the cloud bill. It does nothing to DBU consumption. So on Jobs Compute, where the DBU rate is low and infrastructure is a large share, Spot moves more of the bill. On All-Purpose, where DBUs dominate, fixing the SKU matters more. Know which half you are attacking before you pick the lever.</p>
<p>Levers like these are why classic can still beat serverless on cost for stable workloads, and why it demands more operational maturity. Someone has to decide what's interruption-tolerant, enforce the driver/worker pattern, and keep it consistent.</p>
<p>&gt; <em>The cheapest Databricks configuration is usually the one whose behavior matches the workload, not the one with the lowest nominal unit rate. It also helps to know which levers that configuration actually exposes</em></p>
<h3>Autoscaling That Doesn't Behave How You'd Expect</h3>
<p>Most people picture autoscaling as something that tracks CPU. It doesn't. Databricks describes <a href="https://www.databricks.com/blog/2018/05/02/introducing-databricks-optimized-auto-scaling.html">its optimized autoscaling</a> in terms of workload behavior: worker allocation reacts to job characteristics, primarily the backlog of pending tasks.</p>
<p>A cluster can scale up while its existing nodes sit at 30 percent CPU because the stage produced a lot of small tasks. It can also stay flat under heavy CPU load because the work is never split into enough tasks to create a backlog.</p>
<p>Which leads to five things people get wrong:</p>
<ul>
<li><p><strong>A wide min/max range is not free insurance.</strong> Set 2 to 20, and a burst of small tasks pulls you toward 20, holds those nodes for the stage, and bills you. Autoscaling did its job. The range was the decision, and the range was a guess.</p>
</li>
<li><p><strong>Your minimum is a floor you always pay.</strong> A minimum of 8 workers means you never pay for fewer than 8, including the long tail where one straggler task is finishing.</p>
</li>
<li><p><strong>Streaming does not scale back down the way batch does.</strong> A continuous stream always has work in flight, so the underutilization condition rarely holds. Databricks recommends Lakeflow pipelines with enhanced autoscaling for streaming rather than treating standard autoscaling as universal. They also recommend triggered incremental patterns like AvailableNow when the business does not actually need 24/7 freshness, which is usually the bigger cost question.</p>
</li>
<li><p><strong>Autoscaling does not fix oversizing.</strong> It is a range. Give it the wrong range, and it arrives at a wrong number faster.</p>
</li>
<li><p><strong>Cluster autoscaling and SQL warehouse scaling are not the same system.</strong> Conflating the two is expensive, and it is worth its own explanation below.</p>
</li>
</ul>
<h3>Warehouse size and warehouse scaling are different dials</h3>
<p>A SQL warehouse has two independent settings:</p>
<ul>
<li><p><strong>Size</strong> (2X-Small up to 4X-Large) is how much compute sits behind one cluster. Each step up doubles the <a href="https://docs.databricks.com/aws/en/compute/sql-warehouse/warehouse-behavior">worker count</a>, from 1 worker at 2X-Small to 256 at 4X-Large, and the DBU rate scales with it. A bigger size makes a single heavy query faster.</p>
</li>
<li><p><strong>Scaling</strong> (min and max clusters) is how many identical clusters sit behind the warehouse. More clusters means more queries run at once. It does nothing for the speed of any single query.</p>
</li>
</ul>
<p>To understand, let’s take an example: users say the warehouse is slow. Someone bumps the size, which doubles the rate. But the actual problem was 30 analysts hitting it at 9am and queueing. No query was compute-starved; they were waiting. The size increase does not help, so someone bumps it again. You are now paying four times the original rate for a concurrency problem that more clusters would have fixed at the original size.</p>
<p>The diagnostic is queue time in system.query.history. Significant time waiting for compute usually means scaling out, and long execution with negligible queue time means scaling up. Databricks treats a consistently non-zero queue as a sign that you need either a larger size or more clusters, so check which of the two the queue is telling you before you turn a dial.</p>
<h3>How to Right-Size Clusters and Warehouses</h3>
<p>"Right-sizing" is the most overused and underexplained phrase in Databricks cost conversations. Databricks' <a href="https://docs.databricks.com/aws/en/lakehouse-architecture/cost-optimization/best-practices">cost optimization best practices</a> explain it as:</p>
<blockquote>
<p>Sizing in terms of workload demands: total executor cores, total executor memory, local storage, data partitioning, computational complexity, and parallelism needs. It also recommends starting SQL warehouses at smaller sizes and scaling up only as concurrency and query complexity justify it.</p>
</blockquote>
<p>That sounds reasonable, and it means right-sizing covers several separate decisions rather than one.</p>
<p>It breaks into several separate questions:</p>
<ul>
<li><p>Is this workload interactive SQL, scheduled ETL, ad hoc exploration, streaming, or ML?</p>
</li>
<li><p>Is it on the right compute type at all?</p>
</li>
<li><p>Is the instance family aligned with CPU, memory, shuffle, or caching needs?</p>
</li>
<li><p>Is the driver/worker balance sensible?</p>
</li>
<li><p>Is the warehouse or cluster too large for its actual concurrency pattern?</p>
</li>
<li><p>Is it too small, forcing longer runtime and creating false savings?</p>
</li>
</ul>
<p>This is a rabbit hole for expensive mistakes, and a lot of teams start by equating right-sizing with downsizing.</p>
<p>But downsizing is only one possible outcome. Right-sizing can mean moving smaller, moving to a different instance family, moving a workload from all-purpose to job compute, moving a bursty workload to serverless, or accepting a slightly larger resource because the shorter runtime lowers the total cost.</p>
<p>This distinction becomes more important in mixed Databricks environments where SQL warehouses, Spark jobs, development notebooks, and streaming pipelines all coexist. A team that applies one universal sizing philosophy across all of them usually ends up mis-sizing most of them.</p>
<h2>How to pick a right family instance for jobs</h2>
<p>Instance-family choices are a bit of a cumbersome decision but the highest-impact compute decisions in Databricks cost optimization.</p>
<p>Databricks gives some simple rules of thumb in its AWS guidance:</p>
<ul>
<li><p>memory-optimized for ML, heavy shuffle, and spill-heavy workloads</p>
</li>
<li><p>compute-optimized for structured streaming and maintenance jobs</p>
</li>
<li><p>storage-optimized for workloads that benefit from caching, such as ad hoc or interactive analysis</p>
</li>
<li><p>general-purpose when there is no specific dominant requirement</p>
</li>
<li><p>GPU only where GPU-accelerated libraries actually justify it, per Databricks’ <a href="https://docs.databricks.com/aws/en/lakehouse-architecture/cost-optimization/best-practices">cost optimization best practices</a></p>
</li>
</ul>
<p>The same rules apply to the other cloud providers. Instance family is a cost decision as much as a performance one, because a badly matched family can create waste even when the cluster size itself looks reasonable.</p>
<ul>
<li><p>A memory-heavy job on compute-optimized nodes may spill and run longer than necessary.</p>
</li>
<li><p>A shuffle-heavy workload on the wrong family may look “cheap” per node but cost more overall because of runtime inefficiency.</p>
</li>
<li><p>A cached interactive workload on the wrong shape can waste both time and money.</p>
</li>
</ul>
<p>So if you are trying to understand Databricks compute costs, count the nodes and then ask what kind they are and whether they match the workload pattern you actually have.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/68137cf6-a424-4133-a9a1-e945b690f872.png" alt="Auto Tune Settings modal for job email-job-bi-tool, showing Auto Tune enabled for 1 of 1 tasks with automatic rollback if execution time exceeds 1.5x baseline, and a lineage graph card comparing the current driver (r5.2xlarge, \(0.18/hr) to the applied proposal (r5.xlarge, \)0.09/hr) with the worker type unchanged." style="display:block;margin:0 auto" />

<p><em>Altimate Auto Tune uses workload behavior to determine if the current compute family is optimal for the workload. This gives you clear insights into both your current and our suggested configuration's performance, helping you understand the issue before trusting Altimate’s recommendation to make a change.</em></p>
<h2>Keeping compute right-sized over time</h2>
<p>Now that we have figured out what is required, the instance family, the compute type, and the autoscale range, all of these can be set on the cluster when it is created. Those values can go out of date within a few months, because of</p>
<ul>
<li><p>Concurrency changes</p>
</li>
<li><p>Query patterns change.</p>
</li>
<li><p>Teams change. A development environment becomes shared production infrastructure.</p>
</li>
<li><p>A job that used to be small becomes a major pipeline.</p>
</li>
<li><p>A warehouse sized for one dashboard becomes the default for ten.</p>
</li>
</ul>
<p>Right-sizing is an ongoing process. Databricks recommends regular cost audits, ongoing monitoring, tagging, budgets, dashboards, and revisiting strategies as environments scale or change. This is also where operator (FinOps) trust becomes part of the conversation.</p>
<p>As soon as you move from <em>we should size better</em> to <em>a system should help us keep sizing current,</em> the obvious questions appear:</p>
<ul>
<li><p>How much access does the system need?</p>
</li>
<li><p>What is the blast radius if it gets something wrong?</p>
</li>
<li><p>Is there an approval step?</p>
</li>
<li><p>Is there an audit trail?</p>
</li>
<li><p>Can I dry-run it first?</p>
</li>
<li><p>Can it roll back?</p>
</li>
<li><p>What does rollback restore, and what does it not restore?</p>
</li>
</ul>
<p>Those are healthy questions, especially in production.</p>
<p>That last one is the honest caveat. Rollback restores configuration. It does not restore time. If a change made a pipeline late, rollback fixes the next run, but the data that landed late is still late, and anything downstream already read it as stale.</p>
<h4>How Altimate Auto Tune adds control</h4>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/5be71c05-b51c-4122-925e-6d3fa1c999f4.png" alt="Flowchart of the Auto Tune safety loop: snapshot, apply, verify, then monitor performance, rolling back automatically if it regresses." style="display:block;margin:0 auto" />

<p>That caveat is why Auto Tune leans on scope, verification, and rollback instead of asking you to trust it. It is really two agents, one for jobs and one for SQL warehouses, and each gets its own guardrails.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/8dc31502-3f1e-4dc9-8803-cb7d52d7241a.png" alt="Auto Tune history log for job 'email_to_looker,' listing timestamped audit entries where Auto Tune applied, enabled, or backed off driver changes (such as r5.2xlarge to r5.xlarge and i3.2xlarge to r5.2xlarge), each attributed to the system, a service user, or a named engineer." style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Snapshot, apply, verify:</strong> Every change captures the original config, applies the update, then reads it back to confirm it took. The original is always exactly restorable.</p>
</li>
<li><p><strong>Performance monitoring with automatic backoff:</strong> Auto Tune watches performance after every change, latency for warehouses, run health for jobs, against the recent baseline, and rolls back automatically if something regresses.</p>
</li>
<li><p><strong>Granular and approval-gated:</strong> Control is per job, per task, and per warehouse, and nothing changes until you enable a recommendation. Jobs only change while idle and after policy checks pass.</p>
</li>
<li><p><strong>Stays current:</strong> Once enabled, Auto Tune keeps following newer recommendations as the workload changes, under the same monitoring and backoff. That is how sizing stays current instead of going stale by next quarter.</p>
</li>
<li><p><strong>Fully audited:</strong> Every requested, applied, failed, and backoff event is timestamped: who, which job or task, before, and after. Filterable, exportable.</p>
</li>
</ul>
<p><strong>Savings you can see:</strong> Realized savings, money already banked, are reported separately from potential savings, identified but not yet captured. You can see the savings on the Autonomous Savings summary page, with a breakdown per job and per warehouse is also available if you want to drill down.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/a367847b-a36d-48ff-8fc7-400b74d6ea36.png" alt="Altimate AI Summary dashboard showing $83.37K total projected money savings over the next year, split into $74.20K autonomous and $9.17K assisted, with pie charts breaking savings down by autonomous vs. assisted and by DBU vs. cloud infrastructure." style="display:block;margin:0 auto" />

<h2>Which Compute Type for Which Workload</h2>
<table>
<thead>
<tr>
<th>Workload</th>
<th>Compute</th>
<th>Key settings</th>
</tr>
</thead>
<tbody><tr>
<td>Interactive BI</td>
<td>Serverless SQL warehouse</td>
<td>Right-size, short auto-stop, scale <em>out</em> on concurrency</td>
</tr>
<tr>
<td>Ad hoc SQL and exploration</td>
<td>Serverless, or classic with tight auto-termination</td>
<td>Start smaller than feels comfortable, size up on evidence</td>
</tr>
<tr>
<td>Scheduled ETL and batch</td>
<td>Job compute plus Auto Tune</td>
<td>On-demand driver, spot or fleet workers, narrow autoscale range</td>
</tr>
<tr>
<td>Short frequent jobs</td>
<td>Serverless jobs, or classic with a pool</td>
<td>Measure startup as a share of total runtime first</td>
</tr>
<tr>
<td>Streaming</td>
<td>Job compute, or Lakeflow with enhanced autoscaling</td>
<td>Evaluate triggered (AvailableNow) before assuming always-on</td>
</tr>
<tr>
<td>ML training</td>
<td>All-purpose or job compute with GPU</td>
<td>Pools for iteration, right-sized driver</td>
</tr>
</tbody></table>
<p>The cheapest option depends on the workload. Compute gets expensive when teams pick one out of habit.</p>
<h2>Conclusion</h2>
<p>Databricks compute is easier to manage once you stop treating it as a single bill and start seeing it as a set of cost surfaces with different behaviors.</p>
<p>On the Databricks layer, DBUs measure platform-side compute consumption. On the cloud layer, VMs, disks, and networking turn that consumption into infrastructure cost. Workload-level differences separate all-purpose, job compute, SQL warehouses, serverless, and streaming, and the configuration levers include spot, fleet, autoscaling, auto-termination, and instance-family choice. Most waste comes from drift, mismatches, idle time, and defaults nobody revisited.</p>
<p>Right-sizing is therefore continuous, and visibility is the first phase.</p>
<p>Before teams can optimize Databricks well, they need to see which workloads run where, which compute type they are using, which resources are idle, which clusters drift, which warehouses are oversized, and where their money is actually going. Only then do the later layers make sense: assisted insights, recommended actions, and eventually controlled automation.</p>
<p>Databricks cost management starts with understanding compute. Once you have an understanding of usages, almost every other cost optimization or reduction conversation gets easier to interpret and apply.</p>
<hr />
<p>For Databricks official documentation, see Databricks <a href="https://docs.databricks.com/aws/en/lakehouse-architecture/cost-optimization/best-practices">cost optimization best practices</a><em>, and the well-known</em> <a href="https://www.databricks.com/blog/chaos-control-cost-maturity-journey-databricks"><em>cost maturity journey post</em></a> <em>on their blog.</em></p>
]]></content:encoded></item><item><title><![CDATA[Power User for dbt Can Now Tell You Why Your Model Is Slow]]></title><description><![CDATA[The queries that cost you money usually aren't the ones anyone complains about. A dbt model ships to prod looking fine, then scans ten times the data it needs on every scheduled run for the next six m]]></description><link>https://blog.altimate.ai/power-user-for-dbt-can-now-tell-you-why-your-model-is-slow</link><guid isPermaLink="true">https://blog.altimate.ai/power-user-for-dbt-can-now-tell-you-why-your-model-is-slow</guid><category><![CDATA[dbt]]></category><category><![CDATA[SQL]]></category><category><![CDATA[sql optimize]]></category><category><![CDATA[altimateAI]]></category><dc:creator><![CDATA[Anand Gupta]]></dc:creator><pubDate>Sun, 02 Aug 2026 20:18:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/6a81073d-4498-42f5-b716-cc99edaf592c.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The queries that cost you money usually aren't the ones anyone complains about. A dbt model ships to prod looking fine, then scans ten times the data it needs on every scheduled run for the next six months… Nobody notices, because nothing is broken. It's just quietly expensive.</p>
<p>The ones people <em>do</em> notice are bad enough: a model that used to build in two minutes now takes twenty. If someone asks why, nobody really knows.</p>
<p>But the information needed to spot these issues and answer the questions does exist: your warehouse produces it every time it runs a query. The problem is that almost nobody reads that output, because it was never written for humans.</p>
<p>That changes with the new <a href="https://help.altimate.ai/dbt-power-user/test/queryResults/"><strong>Profile this query</strong> feature in Power User for dbt</a>. One click sends your query to Altimate Code, which runs the warehouse's own diagnostics, reads the output, and tells you in plain language what the query is actually doing and where it's going wrong.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/583dc698-7ae5-4a6c-a078-23033553f183.png" alt="Altimate Code, the agentic data engineering harness, powers many advanced features of Power User for dbt" style="display:block;margin:0 auto" />

<h2>Why slow SQL is so hard to debug</h2>
<p>In a cloud warehouse, SQL is a <em>request</em>, not a set of instructions. You describe the result you want. The warehouse decides how to get it.</p>
<p>That decision-making is invisible. Two queries that look almost identical can behave completely differently. One might read a few thousand rows. The other might scan an entire ten-billion-row table because a filter was written in a way the warehouse couldn't use.</p>
<p>You can't see this by reading the SQL. The SQL describes <em>what</em>, not <em>how</em>. And in modern cloud warehouses, <em>how</em> is exactly where the time and money go. Compute is billed by usage. A query that scans more data than it needs isn't just slow. It's expensive, every single time it runs.</p>
<p>Most dbt users respond to slow queries the only way they can: by guessing. Rewrite a CTE. Add a filter earlier. Try an incremental model. Sometimes it helps. Often it doesn't, because the guess didn't match the actual problem.</p>
<h2>What an execution plan actually tells you</h2>
<p>If you know how to ask, warehouses will tell you exactly how they run a query. Ask with a command like <code>EXPLAIN</code>, and you get back an <strong>execution plan</strong>: the warehouse's step-by-step strategy. Which tables it reads. How much data it expects to scan. How it joins tables together. Where it filters. What each step is estimated to cost.</p>
<p>Some databases go further. <code>EXPLAIN ANALYZE</code> (in Postgres, for example) actually runs the query and reports real numbers: how long each step took, how many rows actually flowed through, whether the work fit in memory.</p>
<p>This is the "ground truth" of query performance. If your query is slow, the reason is in the execution plan.</p>
<p>So why does nobody read them? Three reasons.</p>
<ol>
<li><p><strong>They're dense.</strong> A plan for a moderately complex query can run to hundreds of lines of nested operators, cost units, and internal jargon.</p>
</li>
<li><p><strong>They're inconsistent.</strong> Snowflake, BigQuery, Postgres, and Databricks each format plans differently, use different terminology, and even use different commands to produce them.</p>
</li>
<li><p><strong>They assume expertise.</strong> Reading a plan well means knowing what a <em>hash join</em> is, why "estimated rows: 100, actual rows: 4,000,000" is alarming, and which operators are red flags. That's a database performance skill set, not an analytics engineering one.</p>
</li>
</ol>
<blockquote>
<p><strong>Warehouse execution plans</strong> are like an X-ray of your query: Incredibly informative… if you happen to be a radiologist.</p>
</blockquote>
<h2>What Altimate Code does differently</h2>
<p><a href="https://github.com/AltimateAI/altimate-code/">Altimate Code</a> is an open-source AI coding agent built for data work, with a live connection to your warehouse. That last part is the key. It doesn't just look at your SQL. It can run the diagnostic commands your warehouse supports, get the real plan back, and interpret it.</p>
<p>In other words: it reads the X-ray for you.</p>
<p>Because it knows the differences between warehouse dialects, the same button works whether you're on Snowflake, BigQuery, Postgres, or something else. You don't need to remember which explain command your warehouse uses or what its plan format looks like. (The exact diagnostics available do vary by warehouse. Some expose richer runtime detail than others, so the depth of the profile depends on what your database can report.)</p>
<h2>The dbt profile query workflow</h2>
<p>The whole thing takes one click.</p>
<p>Step 1: <strong>Run a query</strong> in Power User for dbt, as you normally would.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/50c2ffaa-e5ef-49d4-8cbb-079538aeda83.png" alt="Screenshot of the Power User for dbt UI showing the &quot;Run a query&quot; feature." style="display:block;margin:0 auto" />

<p>Step 2: When results load, click "<strong>Profile Query"</strong> in the query results panel toolbar.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/4f99e508-1c7b-4b1f-add8-d1435bfc5b0e.png" alt="Screenshot of the Power User for dbt UI showing  where to click &quot;Profile Query&quot; in the query results panel toolbar" style="display:block;margin:0 auto" />

<p>Step 3: <strong>Altimate Code chat opens</strong> with your SQL and a profiling prompt already in place.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/ed2662ad-4ee8-4eeb-8cf4-f6da8f574832.png" alt="Screenshot of the Power User for dbt UI: Altimate Code chat opens with your SQL and a profiling prompt already in place" style="display:block;margin:0 auto" />

<p>Step 4: The agent runs or interprets the relevant warehouse diagnostics — the execution plan, and runtime statistics where available.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/01ffe52d-6866-4b50-b6b8-a4a50ced44fb.png" alt="Screenshot of the Power User for dbt UI showing Step 4: Altimate Code runs and interprets the warehouse's execution plan and runtime statistics" style="display:block;margin:0 auto" />

<p>Step 5: You get back <strong>plain-language findings</strong>: what the query is doing, where the time and cost are going, and what to try next.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/e3a1d2aa-2672-43d5-b622-c72010af7d50.png" alt="Screenshot of the Power User for dbt UI showing Step 5: Plain-language findings on what the query is doing, where the time and cost are going, and what to try next" style="display:block;margin:0 auto" />

<p>There's also "<strong>Explain with Altimate Code"</strong> in the SQL tab, which does something related but different. More on that distinction below.</p>
<h2>What dbt Query Profiler can actually find</h2>
<p>Here are the kinds of problems that hide in execution plans, and what a profile might surface. These examples are deliberately simple; real findings depend on your data and your warehouse.</p>
<h3>The full table scan</h3>
<pre><code class="language-sql">select
    order_id,
    customer_id,
    order_total
from analytics.fct_orders
where date(created_at) = '2026-08-03'
</code></pre>
<p>This looks fine. It filters to a single day. But wrapping <code>created_at</code> in <code>date()</code> can prevent the warehouse from using <strong>pruning</strong> — its ability to skip chunks of data that can't possibly match the filter. Instead of reading one day's worth of data, it may read the whole table and check every row.</p>
<p>A profile of this query might surface something like:</p>
<blockquote>
<p><em>the plan shows a scan of the full table rather than a pruned range; the</em> <code>date()</code> <em>function on the filter column is likely preventing partition pruning; rewriting the filter as a range on the raw column should let the warehouse skip most of the data:</em></p>
</blockquote>
<pre><code class="language-sql">where created_at &gt;= '2026-07-20'
  and created_at &lt;  '2026-07-21'
</code></pre>
<p>Same result. Potentially a small fraction of the data scanned.</p>
<h3>The join that explodes</h3>
<pre><code class="language-sql">select
    c.customer_id,
    count(*) as event_count
from dim_customers c
join fct_events e
    on c.customer_id = e.customer_id
where e.event_date &gt;= '2026-07-01'
group by 1
</code></pre>
<p>Suppose <code>fct_events</code> is huge, and the plan shows the join producing 200 million intermediate rows before the date filter is applied. That's a <strong>filter applied too late</strong>: the warehouse did an enormous amount of join work, then threw most of it away.</p>
<p>A profile might point out that the row count balloons at the join step, and suggest filtering the events table first (for instance, in a CTE) so the join only touches July's events. The output is identical; the work is not.</p>
<h3>The dbt row estimate that's wildly wrong</h3>
<p>Warehouses plan queries using <strong>row estimates</strong>: guesses about how many rows each step will produce, based on statistics about your data. When those guesses are badly wrong (i.e.: the plan expected just 100 rows and got 4 million) the warehouse may have picked a join strategy or memory allocation that made sense for 100 rows and falls over at 4 million.</p>
<p>This is one of the most common causes of "this query is sometimes fine and sometimes terrible," and it's essentially invisible without looking at a plan. A profile can flag the mismatch and point at the step where the plan's assumptions diverged from reality, which is often the first real clue to stale statistics or a skewed join key.</p>
<h3>The expensive aggregation</h3>
<p>A <code>count(distinct user_id)</code> over a billion rows, or a <code>group by</code> on a high-cardinality column, can dominate a query's runtime, sometimes spilling work to disk when it doesn't fit in memory. The plan shows this. A profile can identify that the aggregation step is where the time goes and suggest alternatives worth testing, like pre-aggregating in an upstream model or, where approximate results are acceptable, an approximate distinct count.</p>
<h2>Explain vs. Profile: what's the difference?</h2>
<p>Power User for dbt now gives you two related (but different) tools:</p>
<p><strong>Explain this query</strong> answers: <em>what does this SQL do?</em> It reads the query and describes the logic: the joins, the filters, the transformations. It's great for understanding unfamiliar code, reviewing a teammate's model, or onboarding onto a project. It doesn't need to touch your data.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/308220e3-186f-4690-915d-2629a42772b0.png" alt="Screenshot of the Power User for dbt UI showing &quot;Explain with Altimate Code&quot; describes the query's logic without touching the warehouse" style="display:block;margin:0 auto" />

<p><em>"Explain with Altimate Code" describes the query's logic without touching the warehouse</em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/9d15caab-9f74-4d75-9c43-479a15884144.png" alt="Screenshot of the Power User for dbt UI showing the &quot;Explain&quot; panel, breaking down joins, filters, and transformations" style="display:block;margin:0 auto" />

<p>The Explain panel breaking down joins, filters, and transformations</p>
<p><strong>Profile this query</strong> answers: <em>how does this query perform against my actual warehouse?</em> It's grounded in diagnostic output from the database: the execution plan, real or estimated row counts, the actual strategy the warehouse chose. It can tell you things no amount of reading the SQL can, because the answer depends on your data: its size, its distribution, how it's clustered or partitioned.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/fca9f2fd-3be0-4ec1-a242-38459d60a360.png" alt="&quot;Profile this query&quot; is grounded in the warehouse's actual execution plan" style="display:block;margin:0 auto" />

<p>"Profile this query" is grounded in the warehouse's actual execution plan</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/438dbccf-5f4f-46df-9f01-b6d1a9eaa75d.png" alt="Screenshot of the Power User for dbt UI showing the Profile panel surfacing real row counts and cost data from the warehouse" style="display:block;margin:0 auto" />

<p>The Profile panel surfacing real row counts and cost data from the warehouse</p>
<p>This is also what separates Power User profiling from pasting your SQL into a general-purpose chatbot. A chatbot can only reason about the text of your query. It doesn't know that your events table is 3TB, that your filter isn't hitting the partition column, or that the optimizer's row estimate was off by four orders of magnitude. Those facts live in your warehouse, and profiling is what brings them into the conversation.</p>
<h2>What health query profiling means in practice</h2>
<p><strong>Cost.</strong> In cloud warehouses, wasted scans are wasted money, compounded by every scheduled run. A model that scans ten times the data it needs isn't a one-time problem — it's a recurring line item. Profiling makes that waste visible while the query is still in front of you.</p>
<p><strong>Speed.</strong> Faster queries mean faster dbt builds, faster CI, faster dashboards. The fixes that profiling points toward — earlier filters, prunable predicates, leaner joins — tend to be small edits with large effects.</p>
<p><strong>Team productivity.</strong> Perhaps the biggest shift is who can do this work. Today, deep query tuning tends to bottleneck on whoever on the team can read plans. Profiling puts a first-pass diagnosis in every analytics engineer's hands. Instead of "this is slow, can someone look at it," the starting point becomes "the profile says the join is exploding before the filter — I'm going to try restructuring it."</p>
<p>One note on positioning: profiling doesn't guarantee a faster query, and it doesn't rewrite your models for you. What it does is close the gap between <em>"this query is slow"</em> and <em>"here is what is likely causing it, and what to try next."</em> It's still a judgment call when it comes to what to change (and whether the tradeoff is right for your model).</p>
<h2>Try dbt query profiler today</h2>
<p>Query Profiler is live in Power User for dbt today. <a href="https://help.altimate.ai/dbt-power-user/test/queryResults/">You will find the docs here</a>. You can access the feature as follows:</p>
<ul>
<li><p><strong>Profile this query</strong>: in the query results panel toolbar, visible once query results are loaded. Run a query, then click it.</p>
</li>
<li><p><strong>Explain with Altimate Code</strong>: in the SQL tab, for when you want to understand what a query does rather than how it performs.</p>
</li>
</ul>
<p>Both open Altimate Code chat with the context already loaded, so you can keep asking follow-up questions: "<em>why is this step expensive?", "What would happen if I filtered earlier?", "Show me the rewritten version."</em></p>
<p>If you're already running Power User for dbt, <strong>update to the latest version</strong> and try it on the slowest model in your project. You may find the answer has been sitting in your warehouse all along, just waiting for someone to read it.</p>
<hr />
<p><a href="https://altimate.ai/products/dbt-power-user"><em>Altimate Code and Power User for dbt (available on VS Code)</em></a> <em>is open source. Have feedback on profiling? We're actively improving dialect coverage and would love to hear what you find.</em></p>
]]></content:encoded></item><item><title><![CDATA[Autonomous Agents for Snowflake Cost Optimization: Announcing Altimate Lite]]></title><description><![CDATA[TL;DR: it saves you money on Snowflake
Altimate Lite is a Snowflake native app that automatically tunes warehouse configuration (auto-suspend, scaling, clustering) roughly every 5-6 seconds to cut com]]></description><link>https://blog.altimate.ai/altimate-lite-autonomous-agents-for-snowflake-cost-optimization</link><guid isPermaLink="true">https://blog.altimate.ai/altimate-lite-autonomous-agents-for-snowflake-cost-optimization</guid><category><![CDATA[snowflake]]></category><category><![CDATA[Snowflake performance]]></category><category><![CDATA[AI costs]]></category><category><![CDATA[AI]]></category><category><![CDATA[altimateAI]]></category><dc:creator><![CDATA[Fraser Marlow]]></dc:creator><pubDate>Tue, 28 Jul 2026 15:28:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/5b60cea4-c56d-4ec0-9b16-038247be852b.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2><strong>TL;DR: it saves you money on Snowflake</strong></h2>
<p><a href="https://app.snowflake.com/marketplace/listing/GZTYZ1VSPRPWK/altimate-ai-altimate-lite-for-ai-and-warehouse-cost-optimization">Altimate Lite is a Snowflake native app</a> that automatically tunes warehouse configuration (auto-suspend, scaling, clustering) roughly every 5-6 seconds to cut compute costs, with no performance impact. Private preview customers saved an average of 19% on warehouse costs, with some seeing savings as high as 57.5%.</p>
<p>As a Snowflake native app, it’s easy to adopt, secure, and can be paid with Snowflake credits. It's free for 21-days, then just $100/month plus 2.5% of the daily cost of any warehouse you activate it on.</p>
<p><a href="https://app.snowflake.com/marketplace/listing/GZTYZ1VSPRPWK/altimate-ai-altimate-lite-for-ai-and-warehouse-cost-optimization">Find it in the Snowflake Marketplace</a> today.</p>
<h2>Watch the Launch video</h2>
<p><a class="embed-card" href="https://www.youtube.com/watch?v=pPDlkjMCSJY">https://www.youtube.com/watch?v=pPDlkjMCSJY</a></p>

<h2>How AI costs get out of hand on Snowflake</h2>
<p>If you think your Snowflake instance is costing more than it should, you are not alone. There are several factors that drive this:</p>
<p>First, a common pattern keeps showing up across Snowflake teams that adopt AI: everything starts to look like an AI problem. Teams transition away from cheap deterministic tooling and start to adopt inference-based solutions across the board. This gets expensive.</p>
<p>Then there is the "Maximilian Fable" persona: always reaching for the newest, most expensive reasoning model. Tasks that a lightweight model like Anthropic’s Haiku would handle just fine often get clobbered with one of the most expensive models like Fable.</p>
<p>Snowflake offers some tooling for tuning your instance, but the process is manual and the audits too far apart to get good results. Snowflake users overspend as a result.</p>
<p>Finally there's cost visibility. Most teams just get a bill at the end of the month, a token count with no breakdown of what drove it. It’s a single total, no itemization, and no way to explain to finOps why this week's number is double last week's.</p>
<p>These costs really add up. There's now a well-known case of a company running up a <a href="https://finance.yahoo.com/sectors/technology/articles/company-blew-500m-claude-ai-173519468.html">$500 million AI bill</a> in a single month because no check was in place and nobody saw it coming.</p>
<p>The fix starts with tracking and visibility: who's consuming AI credits, whether usage is concentrated in a handful of users, and which models and services are actually driving spend.</p>
<h2>Continuous Auto-Tuning: The Other Lever for Cutting Snowflake Warehouse Costs</h2>
<p>Cost isn't just an AI-model problem. It's also a Snowflake warehouse configuration problem.</p>
<p>Snowflake exposes a handful of levers: warehouse size, warehouse type (Gen 1, Gen 2, adaptive), auto-suspend timing, multi-cluster scaling, and max concurrency level. Getting these right, and keeping them right as workloads shift, is normally a manual, periodic exercise: someone looks at usage patterns, makes a best guess, and revisits it weekly or monthly.</p>
<p>What if software made these decisions <em>continuously</em> instead? Not daily reconfiguration but adjusting configuration <strong>every five to six seconds</strong>, a frequency no human team could sustain.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/ee6e31b3-925b-446e-a1b0-829e6d2604ee.png" alt="An Agent Decisions chart showing the daily number of auto-tune configuration changes made over a one-month period." style="display:block;margin:0 auto" />

<p>By comparison, Snowflake's own auto-suspend only probes warehouse activity every 30 seconds; in that same window, Altimate's auto-tune has already run roughly ten checks, looking at idle state, workload shifts, and predicted upcoming load.</p>
<h2>Real World Results: Up to 57.5% in Snowflake Warehouse Savings</h2>
<p>Over the last couple of months during private preview, real Altimate Lite customers saw meaningful savings simply by turning on auto-tune, with no degradation in query performance or queue times:</p>
<ul>
<li><p>Lowest savings observed on any warehouse, any day: <strong>12.4%</strong></p>
</li>
<li><p>Average savings across all customers, warehouses, and days: <strong>19%</strong></p>
</li>
<li><p>Highest single-day savings (typically weekends, when workloads are less consistent): <strong>57.5%</strong></p>
</li>
</ul>
<h2>Inside Altimate Lite: Cost Dashboard, Auto-Tune, and AI Cost Observability</h2>
<p>Altimate Lite is a distilled version of <a href="https://altimate.ai/platform">Altimate's enterprise platform</a> that runs natively on Snowflake. Is was trained on billions of config changes from years of production use. Because it runs entirely inside your Snowflake environment, no data leaves your account, which sidesteps the InfoSec review that a SaaS tool would typically require.</p>
<p><a href="https://www.youtube.com/watch?v=pPDlkjMCSJY">In the demo</a>, Pradnesh walked through the core screens:</p>
<ul>
<li><strong>Cost dashboard</strong>: trending costs, potential annual savings, and how many warehouses are auto-tune eligible vs. already enabled.</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/6dcc9713-eb51-4a80-9dae-3f2330d2089c.png" alt="Altimate Lite warehouse detail page for a dbt pipeline warehouse showing Auto Tune enabled, realized savings of $351, and projected annual savings of $4,269." style="display:block;margin:0 auto" />

<ul>
<li><strong>Per-warehouse view</strong>: estimated 30-day cost, potential (or realized) savings, and a one-click toggle to turn auto-tune on or off.</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/462f2e2d-2b04-412c-8f48-2f111b7abce3.png" alt="Altimate Lite warehouses dashboard showing 30-day total cost, potential annual savings, auto-tune eligible and enabled warehouse counts, and a daily spend and savings chart." style="display:block;margin:0 auto" />

<ul>
<li><strong>Decision history</strong>: a full audit trail of every action taken (cluster suspensions, resize decisions) timestamped and exportable as CSV. On a single warehouse, the system logged 118 tuning decisions in one day.</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/57a5cae5-168c-43cb-9eba-27e007fb1b6d.png" alt="Agent Decisions chart and Auto Tune history log showing a timestamped list of warehouse suspend actions." style="display:block;margin:0 auto" />

<ul>
<li><strong>AI cost observability</strong>: a separate view tracking spend, token usage, and adoption across roughly eight AI services (AI SQL functions, Cortex, Code CLI tools, and more), filterable by service, user, and model, with CSV export for further analysis.</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/5d73219d-b7b2-4f00-a28d-8c777b1d8694.png" alt="Daily AI cost chart in Altimate Lite, stacked by Cortex service, showing spend trends over a one-month period." style="display:block;margin:0 auto" />

<p><em>Daily AI cost chart showing spend trends over a one-month period.</em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/e9db06b8-ab15-498c-a032-e58b365353bb.png" alt="Altimate Lite per-user AI usage detail page showing cost, tokens, queries, and daily spend for a single Snowflake user." style="display:block;margin:0 auto" />

<p><em>Per-user AI usage showing cost, tokens, queries, and daily spend for a single Snowflake user.</em></p>
<h2>Altimate Lite Pricing: Free 21-Day Trial, Then $100/Month</h2>
<p>Altimate made a deliberate choice to keep pricing transparent and self-serve. No sales call required:</p>
<ul>
<li><p><strong>21-day free trial</strong>, no cost.</p>
</li>
<li><p><strong>$100/month</strong> flat fee after the trial.</p>
</li>
<li><p><strong>2.5% of daily warehouse cost (after savings)</strong> for each warehouse you activate auto-tune on. You only pay for the warehouses you turn on, regardless of how many others exist in your account.</p>
</li>
</ul>
<p>The recommended path: turn it on for one or two warehouses, watch the savings and audit history for a bit, and expand from there once you're comfortable.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/6f943f3d-c722-4bf1-9ff0-a9debc753c38.jpg" alt="Find Altimate Lite on the Snowflake Marketplace." style="display:block;margin:0 auto" />

<h2>Altimate Lite vs. Enterprise: What's the Difference?</h2>
<p>Altimate Lite covers auto-tune and AI cost visibility. <a href="https://altimate.ai/platform">The Enterprise edition</a>, which has been running in production for customers processing billions of queries, adds:</p>
<ul>
<li><p><strong>Auto-resize</strong>: automatic warehouse right-sizing as workloads shift.</p>
</li>
<li><p><a href="https://altimate.ai/platform#studio">Altimate</a> <strong>AI Studio</strong>: a collaborative agent workspace for deeper savings analysis, scheduled reporting, and team-based showback/chargeback with SSO integration.</p>
</li>
<li><p><strong>Assisted optimization</strong>: guided recommendations for improving query code, table and storage configuration, and dbt models, safely assignable to teams.</p>
</li>
<li><p><strong>Altimate Code</strong>: <a href="https://github.com/AltimateAI/altimate-code/">an open-source CLI and VS Code extension</a> that catches costly SQL and dbt mistakes during development.</p>
</li>
</ul>
<p>On data handling: Enterprise is a hosted SaaS product that analyzes query history and telemetry (not your underlying business data) to power these features. The Altimate platform is SOC 2 compliant and has been through security review with financial services and healthcare customers, including in Europe.</p>
<h2>Altimate Lite: Key Questions Summary:</h2>
<p><strong>Is Altimate Lite free to try?</strong><br />Yes. Altimate Lite includes a 21-day free trial with no cost. After that, it's $100/month plus 2.5% of the daily cost of any warehouse where you've enabled auto-tune.</p>
<p><strong>Does my data leave my Snowflake account?</strong><br />No. Altimate Lite runs entirely inside your Snowflake environment as a native app, a walled garden, and none of your data ever leaves your account.</p>
<p><strong>How much can I save?</strong><br />Private preview customers saved an average of 19% on warehouse costs, with a low of 12.4% and weekend peaks as high as 57.5%, with no measurable impact on query performance.</p>
<p><strong>How is this different from Snowflake's built-in auto-suspend?</strong><br />Snowflake's auto-suspend checks warehouse activity every 30 seconds. Altimate's auto-tune runs roughly ten checks in that same window and adjusts configuration every five to six seconds based on predicted workload.</p>
<p><strong>How to Get Started with Altimate Lite's Free Trial</strong><br />Altimate Lite is live now on the Snowflake Marketplace. Start your 21-day free trial today. If you want to talk through auto-resize, Enterprise features, or just how to think about AI cost management more broadly, reach out to the Altimate team, no obligations, no high-pressure sales.</p>
]]></content:encoded></item><item><title><![CDATA[What AI Agents Are Really Changing in Data Engineering]]></title><description><![CDATA[Now that job candidates write their resumes and rehearse their interview answers with AI, every application reads the same. "Now every resume is perfect," Pradnesh Patil said on DataCamp's "The New Da]]></description><link>https://blog.altimate.ai/what-ai-agents-are-really-changing-in-data-engineering</link><guid isPermaLink="true">https://blog.altimate.ai/what-ai-agents-are-really-changing-in-data-engineering</guid><category><![CDATA[AI]]></category><category><![CDATA[data-engineering]]></category><dc:creator><![CDATA[Fraser Marlow]]></dc:creator><pubDate>Wed, 22 Jul 2026 13:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/ef646007-af57-4c5a-9cf0-79056ef31c18.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Now that job candidates write their resumes and rehearse their interview answers with AI, every application reads the same. "Now every resume is perfect," Pradnesh Patil said on DataCamp's "<a href="https://www.datacamp.com/resources/webinars/the-new-data-engineering-team">The New Data Engineering Team</a>" panel, part of its Data Science and Engineering Week.</p>
<p>Patil, co-founder and CEO of Altimate AI, joined host Richie Cotton alongside <a href="https://www.linkedin.com/in/nehatharani/">Neha Tharani</a>, data foundation lead at the reinsurer SCOR, and <a href="https://www.linkedin.com/in/lisa-mirkovic/">Lisa Mirkovic</a>, a data and AI strategy adviser who previously ran data engineering at Capital Group. Generative AI changed how data engineers work, and it also broke the funnels companies use to hire them.</p>
<p><a href="https://www.datacamp.com/resources/webinars/the-new-data-engineering-team">Catch the full episode here.</a></p>
<h2>Hiring when the resume stopped carrying signal</h2>
<p>Resumes are not the only signal AI degraded. Video interviews are straightforward to game with live prompting tools, which leaves conversation as a weak test of anything. Altimate AI rebuilt its process around work instead: exercises capped at sixty to ninety minutes, followed by a short discussion. Candidates are told the rules upfront, in Patil's words, "you can use as much AI as you want."</p>
<p>The exercise measures what someone builds with AI available, not whether they can work without it. Patil noted that startups across the San Francisco Bay Area are changing how they interview for the same reason. Skills assessments built around real tasks are displacing credential and resume screening.</p>
<h2>Validate agent output with a data diff, not a second model</h2>
<p>Large language models are probabilistic, so the validation layer around their output is the thing you actually build. Patil's example was SQL. When an agent rewrites or optimizes a query, the test is whether it returns the same data as the original: "is it producing the same data with a new query?" You do not need a second model to check that, only a data diff tool that compares the two result sets directly.</p>
<p>The pattern generalizes to anywhere an agent touches a pipeline, a transformation, or a query. Each of those places needs a lightweight deterministic check attached to it rather than an assumption of correctness.</p>
<h2>AI documents move the cost to the reviewer</h2>
<p>AI also created a collaboration cost that is easy to miss. A teammate generates a six-page document in five minutes, then expects a colleague to spend forty-five minutes reading it. Patil's rule is to edit AI output down before passing it on, because the models are built to overproduce. As he put it, "all these LLM models are text hungry. If you ask it to do something instead of writing five lines, it's going to write five pages."</p>
<h2>Governance became a daily job</h2>
<p>Governance is where the new risks concentrate, and Patil pointed to public incidents rather than hypotheticals: an agent that ran a query costing more than five thousand dollars, and production databases dropped at larger companies. "If you let it scale without guardrail, it's going to do crazy things," he said. A per-tool setting does not contain that, because an agent moves across tools and the guardrail has to move with it. Altimate AI open-sourced a rules-and-permissions framework, Altimate Core, under an MIT license as one starting point.</p>
<h2>Where agents already pay off</h2>
<p>Fenced in properly, agents produce measurable wins. Patil described a Fortune 500 company that built agents to manage its data infrastructure, resizing instances and adjusting configuration automatically as workloads shifted. Utilization climbed and the bill fell by 30 to 40 percent. The reason is bandwidth: "as humans, we can't change infrastructure configurations, thousand times a day, but a machine can."</p>
<p>For platform teams deciding where to deploy agentic automation first, infrastructure tuning is the low-risk, high-return place to start.</p>
<h2>Getting knowledge out of people's heads</h2>
<p>Mirkovic described where a team's working knowledge actually lives, "hidden in Wikis and Slack channels and in a senior developer who is there twenty seven years, and only that person knows quirks that are not even in a GitHub repo."</p>
<p>Patil sees teams democratizing that knowledge so business users self-serve the simple questions and bring back only the hardest 20 percent. That is the direction both agreed on: less work done by hand, more work made repeatable for AI and for everyone else.</p>
<p>Teams building 2026 roadmaps can use that split as the test for where agents belong in the stack and where human judgment still has to lead. If the governance layer is the gap, start from Altimate Core instead of writing your own rules engine.</p>
]]></content:encoded></item><item><title><![CDATA[Why AI Agents Break in Production: The Missing Harness in Your Data Stack]]></title><description><![CDATA[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><link>https://blog.altimate.ai/why-ai-agents-break-in-production-the-missing-harness-in-your-data-stack</link><guid isPermaLink="true">https://blog.altimate.ai/why-ai-agents-break-in-production-the-missing-harness-in-your-data-stack</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Pradnesh Patil]]></dc:creator><pubDate>Wed, 15 Jul 2026 18:50:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/80136cc1-556c-41ad-8d5b-a914072837a2.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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>
<h2>AI Agent Harness vs. System Prompt: Why Context Grounding Matters</h2>
<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>
<h2>Why a Well-Designed Harness Outperforms Larger LLMs (Sonnet vs. Opus Benchmark)</h2>
<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 Anthropic's Sonnet, while competing systems relied on Anthropic's 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>
<h2>Deterministic vs. Probabilistic Reasoning in AI Data Agents</h2>
<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>
<h2>Context Compaction for Long-Running Data Pipelines: Preserving Schema and Lineage</h2>
<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>
<h2>Ungoverned AI Query Costs: A $5,000 Cortex AI Bill Case Study</h2>
<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>
<h2>The Future of Data Engineering: From Hand-Written SQL to Agent Governance</h2>
<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></item><item><title><![CDATA[4 Blind Spots of General Coding Agents in Data Engineering]]></title><description><![CDATA[A coding agent enters the data warehouse
A data engineer drops a one-liner into Claude Code: "Add patient_visit_count to dim_patient." Twenty seconds later, Claude has read the project, scanned source]]></description><link>https://blog.altimate.ai/4-blind-spots-of-general-coding-agents-in-data-engineering</link><guid isPermaLink="true">https://blog.altimate.ai/4-blind-spots-of-general-coding-agents-in-data-engineering</guid><category><![CDATA[data-engineering]]></category><category><![CDATA[AI]]></category><category><![CDATA[llm]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[SQL]]></category><dc:creator><![CDATA[Syed Haider]]></dc:creator><pubDate>Mon, 06 Jul 2026 22:35:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/cb2766a9-9af9-4ce0-9fea-1c78181cc938.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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://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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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></item><item><title><![CDATA[Where AI Agents Belong in Data Engineering: The Correctness Layer]]></title><description><![CDATA[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 singl]]></description><link>https://blog.altimate.ai/where-ai-agents-belong-in-data-engineering-the-correctness-layer</link><guid isPermaLink="true">https://blog.altimate.ai/where-ai-agents-belong-in-data-engineering-the-correctness-layer</guid><category><![CDATA[altimateAI]]></category><category><![CDATA[harnessengineering]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[AI]]></category><category><![CDATA[llm]]></category><dc:creator><![CDATA[Simon Späti]]></dc:creator><pubDate>Mon, 29 Jun 2026 16:47:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/2c9f17df-29cf-4ff3-902c-5d6162b044ae.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://hackmd.io/_uploads/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://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://altimate.ai/blog/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="https://hackmd.io/_uploads/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://altimate.ai/blog/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="https://hackmd.io/_uploads/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://altimate.ai/blog/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="https://hackmd.io/_uploads/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://altimate.ai/blog/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://altimate.ai/blog/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="https://hackmd.io/_uploads/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="https://hackmd.io/_uploads/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="https://hackmd.io/_uploads/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="https://hackmd.io/_uploads/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="https://hackmd.io/_uploads/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://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://altimate.ai/">website</a>.</p>
]]></content:encoded></item><item><title><![CDATA[You Are the Trust Layer: Why AI Code Review Is Breaking Down]]></title><description><![CDATA[Your Job Just Became QA for an AI Pipeline You Didn't Design
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 lo]]></description><link>https://blog.altimate.ai/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale</link><guid isPermaLink="true">https://blog.altimate.ai/you-are-the-trust-layer-managing-data-engineering-ai-agents-at-scale</guid><category><![CDATA[AI]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[developer productivity]]></category><category><![CDATA[llm]]></category><dc:creator><![CDATA[Anand Gupta]]></dc:creator><pubDate>Mon, 15 Jun 2026 19:38:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/0762d2d6-5dab-447e-ace9-fd0a35f099a8.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Your Job Just Became QA for an AI Pipeline You Didn't Design</h2>
<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>
<h2>I Instrumented My Own AI Usage Like a Data Pipeline</h2>
<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>
<blockquote>
<p>I Logged 11,302 AI Requests over two days. Only 37.5% Were Actually Correct.</p>
</blockquote>
<h2>Sub-Agents Are Unmonitored Nodes in Your Pipeline</h2>
<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>
<h2>Why AI Generation Outpaces QA Capacity</h2>
<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>
<h2>96.9% Looked Clean. Only 37.5% Passed Validation.</h2>
<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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/a3a21996-9f63-456d-8ae2-3419691cef5a.png" alt="" style="display:block;margin:0 auto" />

<h2>Bad Lineage Happens One Accepted Diff at a Time</h2>
<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>
<h2>Data Debt Doesn't Show Up on the Dashboard Until It's Expensive</h2>
<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></item><item><title><![CDATA[DeepSeek Cost 62% Less Than Claude. The Surprising Part Wasn't the Savings…]]></title><description><![CDATA[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:

"The cheaper model o]]></description><link>https://blog.altimate.ai/deepseek-vs-claude-sonnet-ai-agent-benchmark</link><guid isPermaLink="true">https://blog.altimate.ai/deepseek-vs-claude-sonnet-ai-agent-benchmark</guid><category><![CDATA[AI]]></category><category><![CDATA[llm]]></category><category><![CDATA[Deepseek]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[Syed Haider]]></dc:creator><pubDate>Wed, 10 Jun 2026 14:33:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/03ea3e21-350a-45e9-87d7-7581b8d9aa92.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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\n114"   ← committed close-but-wrong on turn 8
DeepSeek: "1077"       ← landed correctly after exhaustive schema inspection
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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.ai/products/altimate-code">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://altimate.ai/blog/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></item><item><title><![CDATA[The Great Token Heist of ‘26]]></title><description><![CDATA[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 lo]]></description><link>https://blog.altimate.ai/the-great-token-heist-of-26</link><guid isPermaLink="true">https://blog.altimate.ai/the-great-token-heist-of-26</guid><category><![CDATA[altimateAI]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[Tokenomics]]></category><category><![CDATA[openai]]></category><category><![CDATA[claude-code]]></category><dc:creator><![CDATA[Surya Iyer]]></dc:creator><pubDate>Mon, 01 Jun 2026 20:15:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/a164d003-f725-473b-a6e6-a026ab05d821.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/78d92d86-be82-4f8e-bad2-b499db01ede0.png" alt="" style="display:block;margin:0 auto" />

<hr />
<p><em>— Written from the Altimate team. We build <a href="https://altimate.ai/"><em>Altimate-Code</em></a>, 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></item><item><title><![CDATA[The Correctness Layer]]></title><description><![CDATA[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><link>https://blog.altimate.ai/the-correctness-layer-in-ade</link><guid isPermaLink="true">https://blog.altimate.ai/the-correctness-layer-in-ade</guid><category><![CDATA[agentic AI]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[altimateAI]]></category><dc:creator><![CDATA[Syed Haider]]></dc:creator><pubDate>Wed, 20 May 2026 17:32:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/1871c39e-0eee-4e5f-ba3c-fbf6eb835a79.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We started <a href="https://altimate.ai/products/altimate-code">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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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://altimate.ai/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="https://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></item><item><title><![CDATA[Blast Radius Analysis Using Altimate Code]]></title><description><![CDATA[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's plumbing behind it, electrical wiring w]]></description><link>https://blog.altimate.ai/blast-radius-analysis-using-altimate-code</link><guid isPermaLink="true">https://blog.altimate.ai/blast-radius-analysis-using-altimate-code</guid><category><![CDATA[altimate-code]]></category><category><![CDATA[Data pipelines]]></category><category><![CDATA[dbt]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[snowflake]]></category><category><![CDATA[devtools]]></category><category><![CDATA[#ai-tools]]></category><dc:creator><![CDATA[Muhammad Anas Farooqui]]></dc:creator><pubDate>Mon, 18 May 2026 13:22:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/872f1689-fd5d-494d-b1b9-cf001d92f029.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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></item><item><title><![CDATA[We Created Data Engineering Skills for Claude Code]]></title><description><![CDATA[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><link>https://blog.altimate.ai/we-created-data-engineering-skills-for-claude-code</link><guid isPermaLink="true">https://blog.altimate.ai/we-created-data-engineering-skills-for-claude-code</guid><dc:creator><![CDATA[Steven Johnson]]></dc:creator><pubDate>Mon, 11 May 2026 18:46:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/beb8fcfb-2ed1-4c46-ac6e-d7b964c96314.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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></item><item><title><![CDATA[Best Data Conferences 2026: The Complete Guide]]></title><description><![CDATA[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 ]]></description><link>https://blog.altimate.ai/best-data-conferences-2026-the-complete-guide</link><guid isPermaLink="true">https://blog.altimate.ai/best-data-conferences-2026-the-complete-guide</guid><dc:creator><![CDATA[Steven Johnson]]></dc:creator><pubDate>Mon, 11 May 2026 18:31:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/ee92f384-3c6f-4d0c-90a0-79f0018e6387.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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></item><item><title><![CDATA[Claude Code or Altimate Code for Data Engineering?]]></title><description><![CDATA[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><link>https://blog.altimate.ai/claude-code-or-altimate-code-for-data-engineering</link><guid isPermaLink="true">https://blog.altimate.ai/claude-code-or-altimate-code-for-data-engineering</guid><category><![CDATA[claude-code]]></category><category><![CDATA[altimate-code]]></category><category><![CDATA[altimateAI]]></category><dc:creator><![CDATA[Muhammad Anas Farooqui]]></dc:creator><pubDate>Thu, 23 Apr 2026 17:00:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/a5d2ee61-e0d3-4b90-9909-376d54ed2949.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/c14f12cd-3144-4f50-8c58-2b253ebe2912.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Altimate Code:</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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></item><item><title><![CDATA[We built AI that actually works for data engineering.  We crushed the ADE benchmark.]]></title><description><![CDATA[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><link>https://blog.altimate.ai/introducing-altimate-code</link><guid isPermaLink="true">https://blog.altimate.ai/introducing-altimate-code</guid><category><![CDATA[AI Tool ]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[altimateAI]]></category><dc:creator><![CDATA[Anand Gupta]]></dc:creator><pubDate>Thu, 19 Mar 2026 15:58:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/04d44fc2-99f4-442b-9df5-80debde510b6.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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://altimate.ai/benchmarks">here</a>.</p>
<h2>What the harness catches</h2>
<img src="https://cdn.hashnode.com/uploads/covers/6961decc69c600e13d6a9156/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="https://help.altimate.ai/code/getting-started/">altimate-code.ai</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></item><item><title><![CDATA[Teaching Claude Code the Art of Data Engineering: Introducing Altimate Skills]]></title><description><![CDATA[Today, we'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><link>https://blog.altimate.ai/teaching-claude-code-the-art-of-data-engineering-introducing-altimate-skills</link><guid isPermaLink="true">https://blog.altimate.ai/teaching-claude-code-the-art-of-data-engineering-introducing-altimate-skills</guid><category><![CDATA[datamates]]></category><category><![CDATA[altimate]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[AI skills]]></category><category><![CDATA[aiskills]]></category><category><![CDATA[snowflake]]></category><category><![CDATA[dbt]]></category><category><![CDATA[altimateAI]]></category><category><![CDATA[AI]]></category><category><![CDATA[claude.ai]]></category><category><![CDATA[claude-code]]></category><category><![CDATA[genai]]></category><dc:creator><![CDATA[Anand Gupta]]></dc:creator><pubDate>Thu, 22 Jan 2026 20:31:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769034275423/1048fa9e-42f7-45d3-b2e8-47db897f7d4b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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></item><item><title><![CDATA[Adaptive Compute vs. Auto Tune: A Practical Guide to Optimizing Snowflake Warehouses]]></title><description><![CDATA[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 ]]></description><link>https://blog.altimate.ai/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses</link><guid isPermaLink="true">https://blog.altimate.ai/adaptive-compute-vs-auto-tune-a-practical-guide-to-optimizing-snowflake-warehouses</guid><category><![CDATA[altimateAI]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[snowflake]]></category><category><![CDATA[Snowflake performance]]></category><category><![CDATA[data-warehousing]]></category><dc:creator><![CDATA[Dana Van Aken]]></dc:creator><pubDate>Wed, 30 Jul 2025 22:41:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769225646596/6da7cca8-4c24-457a-80da-e02f4eb8bff6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<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>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>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753758694594/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." style="display:block;margin:0 auto" />

<p><em><strong>Figure 1:</strong></em> <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>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 href="#references-section">1</a>], so don’t build processes around it.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753759729505/44797494-87ad-4e37-ac25-fb978775b24c.png" alt="" style="display:block;margin:0 auto" />

<p><em><strong>Figure 2:</strong></em> <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>Where Adaptive Compute Delivers</h1>
<h3><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><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>
<table>
<thead>
<tr>
<th><strong>Query</strong></th>
<th><strong>Description</strong></th>
<th><strong>Predicted Compute Needs</strong></th>
</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>
<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><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><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>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><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 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><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>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><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 href="#references-section">2</a>, <a href="#references-section">3</a>, <a 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>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>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753760258333/24663eaa-3c07-4d03-be84-ff45f81b1d95.png" alt="" style="display:block;margin:0 auto" />

<p><em><strong>Figure 3:</strong></em> <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><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><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><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>
<table>
<thead>
<tr>
<th><strong>Workload Type</strong></th>
<th><strong>Latency Threshold</strong></th>
<th><strong>Queue Threshold</strong></th>
<th><strong>Rationale</strong></th>
</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>
<h3><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>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753760342882/798f097c-7ae7-42aa-95c2-8b9d2a355511.png" alt="" style="display:block;margin:0 auto" />

<p><em><strong>Figure 4:</strong></em> <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><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>Making the Right Choice: Adaptive vs. Auto Tune</h1>
<p>Here are a few pointers for choosing the right solution.</p>
<h3><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><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><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>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 href="https://app.myaltimate.com/contactus">Reach out to us</a> for a no-cost POC.</p>
<h1>References</h1>
<ol>
<li><p><a 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 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 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 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 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 href="https://app.myaltimate.com/contactus"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729767527955/d9ad5daf-6edc-4c94-a697-80f6cb79cbc5.png" alt="" /></a></p>
]]></content:encoded></item><item><title><![CDATA[Supercharging Cursor IDE: How the dbt Power User Extension’s Embedded MCP Server Unlocks AI-Driven dbt Development]]></title><description><![CDATA[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 ex]]></description><link>https://blog.altimate.ai/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development</link><guid isPermaLink="true">https://blog.altimate.ai/supercharging-cursor-ide-how-the-dbt-power-user-extensions-embedded-mcp-server-unlocks-ai-driven-dbt-development</guid><category><![CDATA[cursor ai]]></category><category><![CDATA[dbt]]></category><category><![CDATA[data-engineering]]></category><category><![CDATA[altimateAI]]></category><category><![CDATA[#ai-tools]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Anand Gupta]]></dc:creator><pubDate>Fri, 21 Mar 2025 02:51:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769226591105/49891252-c36a-48cc-9e28-589ba5ea1d33.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>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>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>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742521074775/64322c3e-e90b-4fff-810e-ea4e6a17b8b1.png" alt="" style="display:block;margin:0 auto" />

<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>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742521115616/21274320-18a7-4b37-9fb5-02818ed815de.png" alt="" style="display:block;margin:0 auto" />

<p><em>Architecture of the MCP Server integration with Cursor.</em></p>
<p><em><strong>The diagram shows the Cursor IDE’s AI assistant interacting with the MCP server via tool requests.</strong></em> <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>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>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>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>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>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>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>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>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>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 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 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></item></channel></rss>