Reducing Snowflake or BigQuery Costs with dbt™: A Practical Playbook (Using Paradime Radar)
Feb 26, 2026
How to Reduce dbt™ Costs: A Step-by-Step Workflow to Cut Warehouse Spend
Your dbt™ project runs flawlessly. Models finish on time. Dashboards stay fresh. Yet your data warehouse bill climbs steadily—month after month. Sound familiar?
The truth is, performance and cost are different problems. You can have fast pipelines that burn through credits, or lean pipelines that deliver results at a fraction of the spend. This guide gives you a repeatable, four-step workflow to systematically find, fix, and validate cost savings in your dbt™ projects—using Paradime Radar and Bolt as your primary instruments.
Figure 1: The four-step cost optimization loop—measure, identify, fix, validate—then repeat.
Why dbt™ Performance Tuning Isn't the Same as Cost Optimization
Before diving into the workflow, it's important to internalize a counterintuitive reality: a fast dbt™ project is not automatically a cheap one.
Fast Can Still Be Expensive
Consider a model that completes in 30 seconds but scans 500 GB of data every run. On Snowflake, that's roughly $2.30 per run in compute alone (at list pricing on a medium warehouse). Run it hourly, and you're looking at ~$1,680/month for a single model—despite the execution being "fast."
Speed is about wall-clock time. Cost is about resources consumed: bytes scanned, warehouse uptime, slot utilization, and how often work is repeated unnecessarily.
Cost Drivers: Scans, Bytes Processed, Concurrency, Reprocessing
The four primary levers that inflate your warehouse bill are:
Cost Driver | Snowflake Impact | BigQuery Impact |
|---|---|---|
Full table scans | More micro-partitions read → longer warehouse uptime → more credits | More bytes processed → higher on-demand cost |
Bytes processed | Larger warehouses needed → higher per-second credit burn | Direct billing multiplier ($6.25/TB on-demand) |
Concurrency | Multiple warehouses running simultaneously; idle warehouse time | Slot contention; potential autoscaler overshoot |
Reprocessing | Full refreshes rebuild entire tables; downstream cascades | Redundant bytes scanned on every run |
Understanding these drivers tells you where to look. The workflow below tells you how to look—and what to do once you find the culprits.
Step 1: Find the Most Expensive Models with Paradime Radar
You can't cut costs you can't see. The first step is establishing cost visibility at the model level—not just the warehouse or project level.
Paradime Radar's Cost Management suite provides AI-driven dashboards that surface spending across both Snowflake and BigQuery, broken down by warehouse, user, project, and—critically—individual dbt™ models.
Cost Hotspots by Model and Time Window
Start with the dbt™ Project Costs view in Radar's Snowflake Cost Monitoring or BigQuery Cost Monitoring dashboards:
Filter by date range (7, 14, 30, or 60 days) to see cost trends over time.
Sort by model cost to identify the top 10 most expensive dbt™ models.
Cross-reference with the User and Query Cost Analysis to see if specific users or ad-hoc queries are driving costs outside your scheduled pipeline.
For BigQuery specifically, Radar's Query-Specific Cost Analysis lets you drill into individual queries by hash, tracking cost-per-execution trends and the processed-to-shuffled bytes ratio—a key signal for query inefficiency.
Figure 2: How to navigate Paradime Radar to surface your costliest dbt™ models.
Detect Regressions After Releases
Cost regressions often slip in after a release—a new JOIN that widens a scan, an accidental SELECT *, or a materialization change that triggers full rebuilds.
Radar's Real-time Alerting catches these automatically:
dbt™ Cost Anomaly Alert: Triggers when a dbt™ model's cost exceeds a set percentage (recommended: 20%) above its 7-day daily average.
Query Cost Anomaly Alert: Same threshold logic, applied to individual queries.
Query Remote Spillage Ratio Anomaly Alert (Snowflake): Fires when bytes spilled to remote storage exceed 5× total bytes scanned—a sign that a query is too large for the current warehouse.
Configure these alerts to notify your team via Slack, Microsoft Teams, or email so you catch regressions within hours, not at the end of the billing cycle.
Step 2: Use Bolt Run Timing Analytics to Spot Inefficiencies
Cost hotspots tell you what is expensive. Bolt's run analytics tell you why—by revealing timing patterns, execution frequency, and materialization behavior across your schedules.
Long-Running Models vs. Frequently-Run Models
Not all expensive models are slow, and not all slow models are expensive. The key is to look at cost as a function of both duration and frequency:
Model Type | Characteristic | Optimization Priority |
|---|---|---|
Long-running + infrequent | 45 min runtime, runs daily | High—refactor the model itself |
Short-running + very frequent | 2 min runtime, runs every 15 min | High—reduce frequency or switch to incremental |
Long-running + frequent | 30 min runtime, runs every hour | Critical—fix both the model and the schedule |
Short-running + infrequent | 1 min runtime, runs daily | Low—likely not worth optimizing |
In Bolt's Run History, inspect:
Duration per run (visible in seconds/minutes for each schedule execution)
Trigger type (manual vs. automatic) to spot unintended ad-hoc runs
Run status patterns over time to identify schedules that fail and retry repeatedly
Use the Radar Schedules Dashboard to see models with highest average run times and the distribution of execution time across dbt™ commands and models within a schedule.
Materialization Mismatch Patterns
The Radar Models Dashboard shows the distribution of materialization types (table, view, incremental, snapshot) across your project. Common mismatches to look for:
Figure 3: Common materialization mismatches and their cost-efficient alternatives.
As a rule of thumb from the dbt™ documentation on materializations:
Views: Best for lightweight transformations (renaming, recasting). No storage cost.
Tables: Best for models queried by BI tools or many downstream dependencies.
Incremental: Best for event-style data or when full rebuilds become too slow/costly.
Ephemeral: Best for very light transformations used in one or two downstream models.
Step 3: Apply the Highest-ROI Fixes
With your cost hotspots identified and inefficiency patterns mapped, it's time to apply fixes—starting with the changes that deliver the biggest savings for the least effort.
Switch Full Refreshes to Incremental
This is almost always the single highest-ROI change. If you have a model that rebuilds a large table from scratch on every run, switching to incremental materialization can reduce bytes processed by 90%+.
Here's the basic pattern from the dbt™ docs:
The is_incremental() macro ensures that on subsequent runs, dbt™ only processes rows newer than the latest timestamp already in the target table. The first run builds the full table; every run after that is an append or merge of new data only.
For more advanced use cases, you can add incremental_predicates to limit the scan on the target table as well:
Partitioning/Clustering Strategies (Warehouse-Specific)
Proper partitioning and clustering ensures your warehouse scans only the data slices it needs.
BigQuery: Partition + Cluster
From the BigQuery dbt™ configurations:
Snowflake: Cluster By
From the Snowflake dbt™ configurations:
Snowflake automatically creates micro-partitions and maintains clustering metadata. Adding cluster_by instructs Snowflake to organize data within those partitions, enabling more efficient partition pruning on filtered queries.
Reduce Scanned Data (Select Fewer Columns, Filter Earlier)
Two simple but high-impact SQL habits:
Never use
SELECT *in production models. Every unused column adds to bytes scanned. This matters enormously in BigQuery (billed per byte) and increases warehouse uptime in Snowflake.Push WHERE filters as early as possible in your DAG. If a staging model can filter out irrelevant rows before they flow downstream, every subsequent model benefits.
Avoid Rebuilding Downstream Marts Unnecessarily
If an upstream staging model hasn't changed, there's no reason to rebuild the downstream mart that depends on it. Strategies to prevent unnecessary work:
Use dbt™'s state-based selection (
--select state:modified+) in CI/CD to build only modified models and their downstream dependents.Consolidate overlapping schedules so the same model isn't built multiple times across different Bolt schedules.
Use the
--deferflag in development and CI environments to reference production artifacts instead of rebuilding every upstream model.
Step 4: Validate Savings and Prevent Regressions
Fixing a costly model is only half the battle. Without validation, you can't prove the savings—and without guardrails, the costs will creep back.
Baseline vs. Post-Change Cost Comparison
Before deploying any optimization, record baselines from Radar:
Figure 4: Example baseline-vs-post-change comparison for a single model converted to incremental.
Use Radar's dbt™ Project Costs dashboard to compare the same model over the same time window before and after the change. Filter to the model name and compare 7-day windows.
Add Guardrails: Tests, CI Checks, Documentation
To prevent future regressions, build guardrails into your project:
1. Add data tests to your schema.yml:
From the dbt™ data tests documentation:
2. Set up CI checks with Paradime Bolt:
Use Bolt's CI/CD template for pull requests to automatically run dbt build and tests when a PR is opened. This catches:
Materialization changes that would revert incremental → table
New
SELECT *patternsBroken relationships or null violations
3. Configure Radar cost anomaly alerts:
Set up the dbt™ Cost Anomaly Alert with a 20% threshold so that if any model's cost spikes above its 7-day average, your team gets notified in Slack or Teams immediately—before the next billing cycle.
Snowflake-Specific Cost Tips
Warehouse Sizing and Auto-Suspend
Snowflake charges per-second for active warehouses, with a 60-second minimum. Two quick wins:
Right-size your warehouses. An XL warehouse costs 2× a Large, which costs 2× a Medium. If your dbt™ models complete in similar time on a Medium as a Large (which is common for I/O-bound queries), you're paying double for no benefit.
Use Paradime Radar's Snowflake Cost Optimization dashboard, which includes:
Warehouse AI Agent Optimizer: Automatically right-sizes warehouses based on historical utilization patterns.
Warehouse AI Autoscaler: Dynamically scales warehouse size based on real-time workload demand.
Idle Time Optimizer: Reduces wasted idle time by tuning auto-suspend intervals.
Set aggressive auto-suspend. Snowflake recommends setting auto-suspend to a low value (1–5 minutes). For dbt™-dedicated warehouses that run on a schedule, 60 seconds is ideal—Bolt triggers the warehouse on demand, so there's no reason to keep it idling.
Micro-Partition Pruning Considerations
Snowflake's performance (and cost) depends heavily on how many micro-partitions it must scan. To maximize pruning:
Align clustering keys with your most common WHERE filters. If downstream queries always filter by
event_date, cluster onevent_date.Filter early in your dbt™ DAG. Staging models should apply date-range filters before data flows downstream.
Avoid large CTEs. CTEs in Snowflake are in-memory constructs that can't be micro-partitioned. If a CTE grows large enough to spill to remote storage, performance degrades dramatically. Persist heavy CTEs as their own dbt™ model (materialized as a table) so Snowflake can partition them.
Check the Query Profile for the "Partitions scanned vs. Partitions total" metric. If you're scanning >50% of partitions on a filtered query, your clustering or filter predicates need attention.
BigQuery-Specific Cost Tips
Bytes Processed and Partition Filters
BigQuery's on-demand pricing bills at $6.25 per TB processed. Every byte scanned counts. The two most impactful levers:
Use partition filters on every query. If a table is partitioned by event_date, any query (or downstream model) that doesn't include a WHERE event_date = ... filter will scan the entire table. BigQuery supports a require_partition_filter option to enforce this:
Combine partitioning with clustering. Partition by your date column for coarse pruning, then cluster by your most common filter/join columns (e.g., user_id, campaign_id) for fine-grained block elimination. BigQuery supports up to four clustering columns.
Use Radar's BigQuery Cost Monitoring dashboard to monitor:
dbt™ Model Cost Analysis to identify models with the highest bytes-processed cost.
Query Performance Metrics to track the processed-to-shuffled bytes ratio over time.
Slot/Concurrency Considerations
BigQuery offers two pricing models:
On-demand: Pay per query based on bytes processed. Simple but unpredictable at scale.
Capacity-based (Editions): Pre-purchase slots (virtual CPUs). Predictable cost, but requires monitoring utilization.
If you're on capacity pricing, use Radar's Slot Usage Analysis to:
Visualize slot consumption patterns across the day.
Identify peak hours where dbt™ schedules compete with BI queries for slots.
Adjust Bolt schedule timing to avoid slot contention—shift heavy dbt™ runs to off-peak hours.
If you're on on-demand pricing and spending >$10K/month, run the math on switching to capacity pricing. Radar's Small Query Waste Anomaly Alert (triggers when billed bytes significantly exceed processed bytes) can also reveal inefficiency from BigQuery's minimum billing threshold on many small queries.
Putting It All Together
dbt™ cost optimization isn't a one-time project—it's a continuous loop. Here's the complete workflow you can repeat every sprint or billing cycle:
Figure 5: The complete cost optimization cycle—repeatable every sprint.
The teams that reduce warehouse spend by 30–50% aren't the ones writing the cleverest SQL. They're the ones who measure systematically, fix the highest-ROI items first, and build guardrails to prevent regressions. With Paradime Radar for visibility and Bolt for orchestration and CI, you have everything you need to turn cost optimization from a quarterly fire drill into a continuous, automated practice.
Start with Step 1 today. Open your Radar dashboard, find your five most expensive models, and ask one question: Does the cost of this model match the value it delivers? The answer will tell you exactly where to begin.


