Snowflake cost at mid-market scale is dominated by warehouse compute (typically 70-85% of the bill), with storage and serverless features making up the rest. The five levers that move the bill: warehouse sizing, auto-suspend tuning, query patterns, materialization strategy, and contract structure. Most savings claims for Snowflake collapse to one of these. Order matters; we cover the order that produces the most savings per week of work.
Why Snowflake cost is its own problem
Snowflake's pricing model has two unusual properties that shape the optimization work:
- Compute is metered in credits per second of warehouse runtime, not by query. A warehouse that idles for an hour with no queries still bills (until auto-suspend, which has minimum 60-second idle time).
- Warehouse size is a multiplier. XS = 1 credit/hr, S = 2, M = 4, L = 8, XL = 16, 2XL = 32, and so on. Doubling warehouse size doubles the per-hour cost. The performance benefit of larger warehouses is workload-dependent — for some queries it's near-linear; for others it's negligible.
The combination means that the same workload can produce a 5-10x bill range depending on warehouse sizing, suspend behavior, and query patterns. There is more decision space here than in EC2 or RDS, where the cost-per-hour curve is more constrained.
This is mid-market territory. Snowflake themselves publish good optimization guidance and have a customer success function for enterprise accounts. For mid-market customers ($10k-$200k/month Snowflake spend) without a dedicated data engineering function, the patterns below are what we run.
The five levers
| Lever | Typical first-pass savings | Effort |
|---|---|---|
| Warehouse sizing | 20-35% of compute | 1 week |
| Auto-suspend tuning | 8-15% of compute | 2 days |
| Query patterns (clustering, pruning, joins) | 15-30% of compute | Ongoing |
| Materialization strategy | 10-25% (use-case-specific) | 1-2 weeks |
| Contract structure | 10-20% on covered usage | Negotiation cycle |
Like the EKS framework, the percentages aren't additive. A typical first-pass on an unoptimized Snowflake account produces 25-45% reduction in monthly credits.
Lever 1: Warehouse sizing
The most common Snowflake sizing mistake we see at mid-market: warehouses are over-sized for the workloads that run on them, because someone benchmarked a single complex query, picked a size that ran it fast, and never revisited.
The diagnostic: pull WAREHOUSE_METERING_HISTORY for the last 30 days for each warehouse. Look at the distribution of query execution times. If P95 query duration on a Medium warehouse is under 30 seconds and P50 is under 5 seconds, you are likely sized for a few outlier queries; the typical query would run on a Small or XS without meaningful user-visible impact.
The corrected approach:
- Separate warehouses by workload type. A warehouse for short interactive queries (BI dashboards, ad-hoc analyst queries) and a separate warehouse for batch ETL is more efficient than one warehouse handling both.
- Right-size each warehouse to its dominant workload. The interactive warehouse can usually be Small or XS; the batch warehouse may need Medium or Large depending on query complexity.
- Use multi-cluster scaling for the interactive warehouse so it scales out for concurrency rather than scaling up for individual query speed.
A typical reorganization for a mid-market Snowflake account:
| Workload | Before | After |
|---|---|---|
| BI dashboards (Looker, Tableau) | Medium, single cluster | XS-Small, multi-cluster (1-4) |
| Ad-hoc analyst queries | Medium, single cluster | Small, multi-cluster (1-3) |
| Scheduled ETL jobs | Medium, single cluster | Medium, single cluster (or X-Small) |
| Heavy ad-hoc / one-off | Medium | Large, manually started for these queries only |
The key insight: pay for the size when you need it, run small the rest of the time. A Medium warehouse running 12 hours a day = 48 credits. A Small warehouse running the same hours plus a Large warehouse running 30 minutes for the heavy queries = 24 + 8 = 32 credits. Same throughput; lower cost.
Lever 2: Auto-suspend tuning
Snowflake's AUTO_SUSPEND parameter controls how long a warehouse stays running after the last query completes. The default is 600 seconds (10 minutes) for warehouses created in the UI; older warehouses might be set higher.
For interactive workloads (analysts running queries with thinking time between them), 60-120 seconds is usually right. The cache benefit of keeping the warehouse warm for follow-up queries dominates the cost benefit of suspending immediately.
For dashboard workloads (queries arriving on a fixed schedule from a BI tool), 60 seconds works.
For ETL workloads (jobs that fire, run, complete), the minimum (60 seconds) is appropriate, or AUTO_SUSPEND can be set higher only if the next ETL job arrives within that window.
A typical mid-market account has multiple warehouses with AUTO_SUSPEND = 600 that should be 60 or 120. Each one represents wasted credit-seconds between queries. The change is one ALTER WAREHOUSE statement per warehouse.
The trap to avoid: setting AUTO_SUSPEND too low (60s) on warehouses serving interactive analyst workloads, where the query cache benefit of keeping warm is real. The right number depends on how often queries arrive on that warehouse; 60 seconds is fine for high-throughput workloads and wrong for low-throughput-but-bursty ones.
Lever 3: Query patterns
The cheapest query is the one that doesn't scan as much data. Snowflake's pruning, micro-partition design, and clustering features all serve this end.
The most impactful query-pattern changes we make in engagements:
Clustering keys on large tables. Snowflake tables are stored in micro-partitions; clustering on a column that is frequently filtered enables pruning to skip most partitions for filtered queries. A WHERE customer_id = X query on a 5TB table not clustered on customer_id may scan most of the table; clustered, it scans the partitions containing that customer's data.
ALTER TABLE events CLUSTER BY (event_date, customer_id);The cost: clustering keys cause Snowflake to incur background reclustering credits as data is added. For high-write tables, this can become meaningful. Monitor AUTOMATIC_CLUSTERING_HISTORY after enabling.
Avoid SELECT *. Snowflake is columnar; it only reads the columns referenced. SELECT * FROM big_table reads every column even if downstream only uses three. The fix is changing application code to specify columns; tedious but effective.
Result caching. Snowflake caches query results for 24 hours. Identical queries hit the cache and return without consuming credits. The catch: any change in the underlying tables invalidates the cache for queries against them. For dashboards that re-query frequently against tables that update less frequently, ensure the dashboard tool sends the same query text each time (some BI tools add timestamps or random nonces that prevent cache hits).
Materialized views and search optimization for repetitive query patterns. Snowflake's materialized views maintain pre-computed results; the search optimization service builds an index for point lookups. Both add ongoing credit cost; both reduce per-query cost. Use when the per-query savings outweigh the maintenance cost — typically when a query pattern fires hundreds of times per day.
Lever 4: Materialization strategy
The architectural decision that most affects Snowflake cost at mid-market scale: how much of the data pipeline runs in Snowflake vs in a warehouse-adjacent system.
A common pattern: dbt models that build complex transformations in Snowflake, with each model triggering a query that runs on a Snowflake warehouse. The credits add up.
Alternatives that reduce Snowflake credit consumption:
- Pre-aggregate upstream. If your raw events table is 1B rows and your dashboard always queries hourly aggregates, materialize the hourly aggregates in a smaller table. Subsequent queries hit the smaller table. This is dbt incremental modeling; if you're already doing it, skip this.
- Move heavy computation outside Snowflake. For ML feature computation, consider Spark on EMR or Databricks for the transformation step, with the result loaded into Snowflake. Snowflake's compute pricing for heavy transformation can be 2-4x more expensive than Spark on Spot instances.
- Use Snowflake for what it's good at. Snowflake excels at concurrent analytical queries on structured data. It's expensive for batch transformation, ML training, and unstructured data processing. Match the workload to the right system.
The materialization strategy is the highest-leverage long-term lever and the slowest to act on. It involves architecture changes that take weeks. We typically address it after the quick wins (warehouse sizing, auto-suspend) are done.
Lever 5: Contract structure
Snowflake's commercial structure has several knobs that affect cost on the same usage:
- On-demand vs capacity contract. On-demand is pay-as-you-go at list price. Capacity contracts commit to a credit pool over a term (typically 1-3 years) at a discount. Discounts are negotiable; typical mid-market discounts on a 1-year capacity contract are 10-20%.
- Edition. Standard, Enterprise, and Business Critical have different per-credit prices. Enterprise enables features (multi-cluster, materialized views, search optimization) that may be necessary for the optimizations above; Business Critical adds compliance features. Pick the edition you need; don't over-buy.
- Storage tier. Snowflake's storage pricing is straightforward; the optimization lever is data lifecycle (deleting old data, dropping unused tables, time-travel retention tuning).
The contract negotiation usually happens at renewal. Going into renewal with the data — credit consumption history, projected growth, what you would have to commit for what discount — matters more than the negotiation tactics. Have the data ready 60 days before renewal.
What to measure
The ongoing measurements that matter:
- Credits per warehouse per week. Trend should be flat or declining as workloads stay constant or as optimizations land. Sudden increases trigger investigation.
- Average warehouse utilization. Queries running per warehouse-hour. Low utilization (< 30%) on an active warehouse suggests sizing or auto-suspend issues.
- Top 10 queries by credits consumed (last 30 days). From
QUERY_HISTORY. This list usually contains the highest-leverage optimization targets. - Storage growth rate. Monthly TB added. Growing faster than business growth suggests data-retention review is needed.
We surface these in a simple dashboard the data team reviews weekly. Native Snowsight dashboards work; third-party tools (Select.dev, Capital One's Slingshot, Sundeck) add value as spend scales but aren't necessary at mid-market.
When specialist tooling pays back
Snowflake observability tools (Select.dev, Sundeck, Slingshot) deliver value when:
- Spend is over $30k/month
- The data team is small and lacks bandwidth for ongoing optimization
- Multiple teams query Snowflake and attribution is a problem
Below that threshold, the native ACCOUNT_USAGE views plus a set of tracked queries are sufficient.
Implementation order for an unoptimized account
- Week 1: Audit warehouses. Set
AUTO_SUSPENDto 60-120s for all interactive workloads. Identify warehouses serving multiple workload types. - Week 2: Right-size warehouses based on the workload-type analysis. Move dashboards to multi-cluster XS/Small. Move ETL to single-cluster sizing matched to job complexity.
- Week 3: Query pattern review. Identify the top 10 most expensive queries. Apply clustering keys, fix
SELECT *patterns, ensure result caching is working. - Week 4: Storage review. Review long-time-travel retention on large tables. Drop unused tables and zero-row tables.
- Ongoing: Materialization strategy review (architectural; quarter-scale work). Contract negotiation at renewal.
After the four-week pass, ongoing work is the weekly review of the metrics above and incremental query-level optimizations as they surface.
Where this advice doesn't fit
- Real-time / streaming workloads. Snowflake supports streaming via Snowpipe and dynamic tables, but cost optimization for streaming is a different problem. The patterns here apply mostly to batch and interactive.
- Heavy ML training in Snowflake. Snowflake has Snowpark and ML features; cost-optimizing ML training in Snowflake involves different levers than analytical queries. Worth a separate post.
- Single-warehouse setups. If you have one warehouse and 100% of usage is on it, the workload-separation advice doesn't apply directly. Often the right move is to add the workload separation as part of the optimization.
FAQ
Q: Should we move from Snowflake to a different warehouse to save money? Sometimes. BigQuery, Redshift, Databricks SQL each have cost profiles that beat Snowflake on specific workload shapes. The migration cost is meaningful; we have done both directions on engagements. Run the analysis before assuming the platform change is the answer; usually optimization within Snowflake closes most of the gap with less risk.
Q: How do credit cost projections work for budgeting? Project forward from the trailing 90 days of usage, adjusted for known upcoming workloads (a new dashboard, a new data source). Budget with a 15-20% buffer for surprises. Snowflake's resource monitors can hard-cap spend at warehouse or account level if budget overruns must be prevented.
Q: What about Snowflake's serverless features (Snowpipe, Tasks, dynamic tables)? They have separate pricing models, billed in credits but not tied to a warehouse. Audit them as a separate line item. For most mid-market accounts, serverless features are a small share of cost; the warehouse compute work above is higher leverage.
Q: Does Snowflake's caching make this all moot if we structure queries right? The caching helps. It's part of the optimization toolkit, not a substitute for the others. Cache hit rates depend on query patterns and update frequency; a well-tuned account uses caching well *and* runs right-sized warehouses.
Q: We are evaluating Snowflake against alternatives. What should we look at? Beyond the per-query cost comparison, evaluate: feature parity for your specific use cases, ecosystem integrations (BI tools, data platforms, ETL connectors), team skill set, total cost of ownership including engineering time. Pure cost rarely decides correctly.
*For broader mid-market FinOps practice this fits into, see our pillar on FinOps for 50-500 person companies.*

