Home / Snowflake / Reduce Snowflake costs
Guide
How to reduce Snowflake costs: 15 tactics with example SQL
For data engineers, platform owners and FinOps teams who pay a Snowflake bill. This guide covers the specific Snowflake features that control spend, from ACCOUNT_USAGE views and Cost Insights to auto-suspend, resource monitors, budgets, Time Travel and serverless features, with SQL you can run today. Want it done for you? See our Snowflake cost optimization service.
Quick answer
How do you reduce Snowflake costs?
Measure first: use the ACCOUNT_USAGE views (WAREHOUSE_METERING_HISTORY, QUERY_ATTRIBUTION_HISTORY) and Cost Insights to see which warehouses, queries and features use credits. Then set auto-suspend to about 60 seconds, right-size and split warehouses, add statement timeouts, fix queries that scan too much data, shorten Time Travel on staging tables, review serverless features, and cap spend with resource monitors and budgets.
How billing works
What you are paying for
Snowflake bills compute in credits. Warehouses use credits per second while running, with a 60-second minimum each time they resume, and each size step doubles the hourly rate. Serverless features use credits on their own. Cloud services are billed only for the part above 10% of that day's warehouse usage. Storage is billed per terabyte per month. The dollar price of a credit depends on your edition, cloud region and contract.
| Cost line | Main levers | Tactics |
|---|---|---|
| Warehouses | Auto-suspend, size, scaling policy, timeouts, query design | 3–8 |
| Serverless | Clustering, materialized views, search optimization, Snowpipe, tasks | 9, 10, 12 |
| Storage | Time Travel retention, transient tables, unused data | 11 |
| Visibility | Usage views, Cost Insights, monitors, budgets, tags | 1, 2, 13–15 |
Tactics 1–2 · Measure
See where the money goes
Understand where credits go
Your bill has three main parts: compute (virtual warehouses), serverless features (Snowpipe, automatic clustering, serverless tasks and others) and storage. Start with credits by service type, then by warehouse, then by query. The views in
SNOWFLAKE.ACCOUNT_USAGElag by up to a few hours, so look at the last 7 to 30 days.-- Credits billed by service type, last 30 days SELECT service_type, ROUND(SUM(credits_billed), 1) AS credits_billed FROM snowflake.account_usage.metering_daily_history WHERE usage_date >= DATEADD(day, -30, CURRENT_DATE()) GROUP BY service_type ORDER BY credits_billed DESC; -- Most expensive repeated queries, last 7 days SELECT query_parameterized_hash, ANY_VALUE(warehouse_name) AS warehouse, COUNT(*) AS runs, ROUND(SUM(credits_attributed_compute), 2) AS credits FROM snowflake.account_usage.query_attribution_history WHERE start_time >= DATEADD(day, -7, CURRENT_TIMESTAMP()) GROUP BY query_parameterized_hash ORDER BY credits DESC LIMIT 20;QUERY_ATTRIBUTION_HISTORYexcludes warehouse idle time and very short queries, so its total will be lower thanWAREHOUSE_METERING_HISTORY. The gap between the two is roughly your idle cost, which tactic 3 attacks.Check Cost Insights in Snowsight
Snowflake's Cost Insights appear in Snowsight under Admin » Cost management » Account Overview, in the Optimization insights tile. Snowflake recalculates them weekly. They flag items such as rarely used tables with automatic clustering, rarely used materialized views and search optimization paths, large tables that are never queried, short-lived permanent tables, active warehouses with large gaps between queries, and inefficient multi-cluster usage. Each is a ready-made shortlist for tactics 9 to 11.
Tactics 3–6 · Compute
Stop paying for idle and oversized warehouses
Set auto-suspend to about 60 seconds
A running warehouse bills per second even with no queries, with a 60-second minimum each time it resumes. Long auto-suspend timers are the most common source of idle spend. Sixty seconds suits loading and transformation warehouses. BI warehouses can justify a few minutes, because suspending drops the local data cache that makes dashboards fast.
SHOW WAREHOUSES; SELECT "name", "size", "auto_suspend" FROM TABLE(RESULT_SCAN(LAST_QUERY_ID())) WHERE "auto_suspend" IS NULL OR "auto_suspend" = 0 OR "auto_suspend" > 300; ALTER WAREHOUSE transform_wh SET AUTO_SUSPEND = 60 AUTO_RESUME = TRUE;Setting it below 60 seconds rarely helps, because of the per-resume minimum. Also check for BI tools or schedulers that send a query every few minutes and keep a warehouse awake all day.
Right-size warehouses and split workloads
Each size step doubles the credit rate: X-Small uses 1 credit per hour, Small 2, Medium 4, Large 8, and so on. A larger warehouse can finish a heavy query faster and cost the same, but light queries on a large warehouse just cost more. Look for warehouses with little spilling and short queries, and test them one size smaller.
SELECT warehouse_name, warehouse_size, COUNT(*) AS queries, ROUND(AVG(total_elapsed_time) / 1000, 1) AS avg_seconds, ROUND(SUM(bytes_spilled_to_remote_storage) / POWER(1024, 3), 1) AS remote_spill_gb, ROUND(AVG(queued_overload_time) / 1000, 1) AS avg_queue_seconds FROM snowflake.account_usage.query_history WHERE start_time >= DATEADD(day, -14, CURRENT_TIMESTAMP()) AND warehouse_name IS NOT NULL GROUP BY warehouse_name, warehouse_size ORDER BY warehouse_name;Remote spilling means the warehouse is too small for that work; none at all, with short run times, suggests it may be too big. Mixed workloads are the other trap: one heavy nightly job sets the size for everything sharing the warehouse. Separate warehouses for loading, transformation and BI let each run at its own size.
Use the Economy scaling policy for multi-cluster warehouses
Multi-cluster warehouses (Enterprise Edition and higher) add clusters when concurrency rises. The default Standard policy starts a cluster as soon as queries queue. Economy starts one only when there is enough load to keep it busy for about six minutes, trading a little queueing for fewer clusters. Keep the minimum at 1 unless you have steady concurrency all day.
ALTER WAREHOUSE bi_wh SET MIN_CLUSTER_COUNT = 1 MAX_CLUSTER_COUNT = 3 SCALING_POLICY = 'ECONOMY';Use Standard for user-facing dashboards where queueing is visible; use Economy for batch and internal reporting.
Add statement timeouts
The default
STATEMENT_TIMEOUT_IN_SECONDSis 172,800 seconds (two days), so a bad join can run on a large warehouse for a very long time. Set a limit per warehouse that fits its workload, and a queue timeout so jobs don't pile up.ALTER WAREHOUSE bi_wh SET STATEMENT_TIMEOUT_IN_SECONDS = 1800 STATEMENT_QUEUED_TIMEOUT_IN_SECONDS = 600;The parameter can also be set at account, user and session level; the lowest applicable value wins.
Tactics 7–10 · Queries
Make each query do less work
Fix queries that scan too much data
Snowflake stores tables in micro-partitions and skips the ones a filter rules out (pruning). Queries that scan most partitions of a large table are usually the most expensive ones you can fix.
SELECT query_id, warehouse_name, partitions_scanned, partitions_total, ROUND(bytes_scanned / POWER(1024, 3), 1) AS gb_scanned, ROUND(total_elapsed_time / 1000) AS seconds FROM snowflake.account_usage.query_history WHERE start_time >= DATEADD(day, -7, CURRENT_TIMESTAMP()) AND partitions_total > 1000 AND partitions_scanned / partitions_total > 0.8 ORDER BY bytes_scanned DESC LIMIT 25;Common fixes: replace
SELECT *with the columns you need (Snowflake stores data by column, so fewer columns means less data read); filter on a date or other well-clustered column; avoid wrapping filter columns in functions; filter before joins; and switch full-refresh dbt models to incremental ones. Use Query Profile in Snowsight to see where time and bytes go. Our database optimization guide covers the query side in more depth.Let the result cache work
Snowflake keeps query results for 24 hours (extended each time they are reused, up to 31 days). If the same query text runs again and the underlying data has not changed, the result returns without running the query on a warehouse. Small differences in the text, such as letter case or table aliases, prevent reuse, and so do functions such as
RANDOM()orUUID_STRING(). Make BI tools send stable query text, and avoid disablingUSE_CACHED_RESULT.Review clustering keys and automatic clustering
A clustering key helps large tables that are filtered on the same column most of the time. Automatic clustering then runs as a serverless feature and costs credits every time data changes. It pays off when the table is queried often and changes less often.
SELECT SYSTEM$CLUSTERING_INFORMATION('analytics.sales.orders', '(order_date)'); SELECT table_name, ROUND(SUM(credits_used), 1) AS credits_30d FROM snowflake.account_usage.automatic_clustering_history WHERE start_time >= DATEADD(day, -30, CURRENT_TIMESTAMP()) GROUP BY table_name ORDER BY credits_30d DESC; ALTER TABLE analytics.sales.orders SUSPEND RECLUSTER;Suspend or drop clustering on tables that are rarely queried, as Cost Insights may already be telling you.
Weigh materialized views and search optimization
Materialized views and the search optimization service (both Enterprise Edition features) speed up specific query patterns, but Snowflake maintains them in the background with serverless credits plus extra storage. They are worth it for a frequently run query on a large, slowly changing table, and rarely worth it on tables with heavy updates or few readers. Use
SYSTEM$ESTIMATE_SEARCH_OPTIMIZATION_COSTSbefore enabling search optimization, and track spend inMATERIALIZED_VIEW_REFRESH_HISTORYandSEARCH_OPTIMIZATION_HISTORY.ALTER TABLE analytics.web.events DROP SEARCH OPTIMIZATION;
Tactics 11–12 · Storage and serverless
Cut background and storage costs
Trim Time Travel, use transient tables and know Fail-safe
Storage is billed per terabyte per month, and it includes Time Travel and Fail-safe copies of changed data. Permanent tables keep changed data for their Time Travel period (up to 1 day on Standard Edition, up to 90 days on Enterprise and higher) plus a 7-day Fail-safe you cannot turn off. Transient and temporary tables have at most 1 day of Time Travel and no Fail-safe, which suits staging data you can reload.
SELECT table_catalog, table_schema, table_name, ROUND(active_bytes / POWER(1024, 4), 2) AS active_tb, ROUND(time_travel_bytes / POWER(1024, 4), 2) AS time_travel_tb, ROUND(failsafe_bytes / POWER(1024, 4), 2) AS failsafe_tb FROM snowflake.account_usage.table_storage_metrics WHERE deleted = FALSE ORDER BY time_travel_bytes + failsafe_bytes DESC LIMIT 20; ALTER SCHEMA staging SET DATA_RETENTION_TIME_IN_DAYS = 1; CREATE TRANSIENT TABLE staging.orders_raw_t AS SELECT * FROM staging.orders_raw;You cannot alter a permanent table into a transient one; recreate it as shown, then swap names. Also drop unused tables, old clones and files left in internal stages.
Watch serverless features: Snowpipe, tasks and auto-clustering
Serverless features bill on their own lines and are not capped by warehouse resource monitors. Snowpipe now charges a fixed number of credits per GB loaded in all editions (Snowflake's December 2025 release note gives 0.0037 credits per GB; check the current Service Consumption Table). Text files such as CSV and JSON are billed on uncompressed size, so the same data in Parquet can bill less. Serverless tasks, automatic clustering, replication and others each show up as a
service_typein tactic 1's query.CREATE OR REPLACE TASK load_orders WAREHOUSE = transform_wh SCHEDULE = '15 MINUTE' WHEN SYSTEM$STREAM_HAS_DATA('raw.orders_stream') AS INSERT INTO core.orders SELECT order_id, customer_id, amount, updated_at FROM raw.orders_stream;The
WHENcondition is checked without starting the warehouse, so a task that runs every 15 minutes only uses compute when there is new data.
Tactics 13–15 · Guardrails
Keep costs from creeping back
Set resource monitors on warehouses
A resource monitor tracks warehouse credits against a quota and can notify, suspend after running queries finish, or suspend immediately. By default only ACCOUNTADMIN can create one. Monitors cover warehouses only, not serverless features.
CREATE OR REPLACE RESOURCE MONITOR rm_transform WITH CREDIT_QUOTA = 500 FREQUENCY = MONTHLY START_TIMESTAMP = IMMEDIATELY TRIGGERS ON 75 PERCENT DO NOTIFY ON 90 PERCENT DO SUSPEND ON 100 PERCENT DO SUSPEND_IMMEDIATE; ALTER WAREHOUSE transform_wh SET RESOURCE_MONITOR = rm_transform;Use budgets for account-wide and serverless spend
Budgets cover a calendar month and include serverless features, so they fill the gap that resource monitors leave. They alert; they do not stop work. Activate the account budget in Snowsight, then create custom budgets for teams or projects (up to 100 per account).
CREATE SNOWFLAKE.CORE.BUDGET budgets_db.budgets_schema.finance_budget(); CALL budgets_db.budgets_schema.finance_budget!SET_SPENDING_LIMIT(500); CALL budgets_db.budgets_schema.finance_budget!ADD_RESOURCE( SELECT SYSTEM$REFERENCE('WAREHOUSE', 'finance_wh', 'SESSION', 'applybudget'));The role needs the SNOWFLAKE.BUDGET_CREATOR database role and APPLYBUDGET on each object it adds. Notification emails must be verified first.
Tag warehouses and queries for chargeback
Costs fall fastest when each team sees its own number. Tag dedicated warehouses with a cost center; for shared warehouses, set a
QUERY_TAGper tool or team and report fromQUERY_ATTRIBUTION_HISTORY.CREATE TAG IF NOT EXISTS governance.tags.cost_center; ALTER WAREHOUSE finance_wh SET TAG governance.tags.cost_center = 'finance'; SELECT tr.tag_value AS cost_center, ROUND(SUM(wmh.credits_used), 1) AS credits_30d FROM snowflake.account_usage.warehouse_metering_history wmh JOIN snowflake.account_usage.tag_references tr ON tr.object_name = wmh.warehouse_name AND tr.domain = 'WAREHOUSE' AND tr.tag_name = 'COST_CENTER' WHERE wmh.start_time >= DATEADD(day, -30, CURRENT_TIMESTAMP()) GROUP BY tr.tag_value ORDER BY credits_30d DESC;For shared warehouses:
ALTER SESSION SET QUERY_TAG = 'team:marketing';in each tool's connection settings, then group attribution history byquery_tag.
Worked example
Example: what one auto-suspend setting costs
Hypothetical numbers, for illustration only. A Medium warehouse (4 credits per hour) runs a transformation job every 30 minutes, 48 times a day. Each run takes 3 minutes. Auto-suspend is set to 10 minutes.
Before: each run keeps the warehouse up for 3 + 10 = 13 minutes. 48 × 13 = 624 minutes, or 10.4 hours a day. 10.4 h × 4 credits = 41.6 credits a day.
After (auto-suspend 60 seconds): 48 × (3 + 1) = 192 minutes, or 3.2 hours. 3.2 h × 4 credits = 12.8 credits a day.
Difference: 28.8 credits a day, about 864 credits over 30 days. At an example price of $3.00 per credit, that is about $2,592 a month for one setting on one warehouse. Your price per credit varies by edition, cloud region and contract, so multiply by your own rate.
The formula
- Warehouse cost = hours running × credits per hour for its size × price per credit
- Hours running includes idle time before auto-suspend
- Each resume is billed for at least 60 seconds
- Multi-cluster: multiply by the number of clusters running
- Check actuals in WAREHOUSE_METERING_HISTORY, not estimates
Prioritised checklist
Where to start: effort vs impact
A typical order of work. Impact is relative and depends on how your account is run today; measure before and after in the usage views.
| Action | Effort | Typical impact | Tactic |
|---|---|---|---|
| Auto-suspend ≈ 60 s on load/transform warehouses | Low | High | 3 |
| Statement and queue timeouts | Low | Medium | 6 |
| Resource monitors and budgets | Low | Medium | 13, 14 |
| Act on Cost Insights findings | Low | Medium | 2 |
| Right-size and split warehouses | Medium | High | 4 |
| Economy scaling policy | Low | Medium | 5 |
| Shorter Time Travel, transient staging tables | Medium | Medium | 11 |
| Review clustering, MVs, search optimization | Medium | Medium | 9, 10 |
| Task WHEN conditions, Snowpipe file formats | Medium | Low–Medium | 12 |
| Rewrite top 20 queries, incremental models | High | High | 7, 8 |
| Tagging and chargeback reporting | Medium | High over time | 15 |
Need hands to do this? Our cost optimization service delivers a ranked list of fixes with estimated savings from read-only ACCOUNT_USAGE access. For ongoing work, Snowflake developers can join your team, or see our wider Snowflake consulting services. Moving from another warehouse? Plan cost guardrails into your Snowflake migration from day one.
Contact us
Ask for a Snowflake cost review
Tell us roughly what you spend on Snowflake each month and what has grown. We'll reply with where we'd look first.
- A senior engineer reads every message
- Reply within one business day
- No obligation, and your details are used only to reply
Prefer the full form? Go to the contact page.
FAQ
Questions about reducing Snowflake costs
What is the fastest way to reduce Snowflake costs?
Set auto-suspend to about 60 seconds on loading and transformation warehouses, step oversized warehouses down one size, and add statement timeouts. These are configuration changes you can make in an afternoon, and they target idle and oversized compute, the most common sources of waste.
How much does a Snowflake credit cost?
It depends on your edition (Standard, Enterprise, Business Critical), cloud provider, region and whether you buy on demand or through a capacity contract. Check your contract or Snowflake's pricing page, then multiply by the credits in WAREHOUSE_METERING_HISTORY and METERING_DAILY_HISTORY.
What is the best auto-suspend setting for a Snowflake warehouse?
About 60 seconds for loading and transformation warehouses. BI warehouses can justify a few minutes so the local cache survives between dashboard queries. Going below 60 seconds rarely helps because each resume is billed for at least 60 seconds.
Do resource monitors limit serverless costs?
No. Resource monitors track and suspend warehouses only. Use budgets, which include serverless features such as Snowpipe, automatic clustering and serverless tasks, to get alerts on that spend.
Does Snowflake charge for an idle warehouse?
Yes, while it is running. A started warehouse bills per second whether or not queries are running, until it suspends. A suspended warehouse costs nothing for compute.
Is compute or storage the bigger Snowflake cost?
For most accounts, warehouse compute is the larger share, but check your own split: compare METERING_DAILY_HISTORY with storage usage in Snowsight cost management. Large Time Travel settings and old clones can make storage significant.
Will a smaller warehouse make queries slower?
Sometimes. Light queries often run just as fast one size down. Heavy queries that spill to remote storage may run longer and cost about the same or more. Test one step down and watch spilling and queue times in QUERY_HISTORY.
When should we get outside help with Snowflake costs?
When spend keeps growing after the basic settings are fixed, when nobody can explain the bill by team, or when the fixes need query rewrites across many pipelines. Our Snowflake cost optimization service starts with a read-only review of your ACCOUNT_USAGE data.
Next step
Tell us what you need to build or who you need to hire.
A 30-minute call with a senior architect. You leave with a scoped plan or a role profile, whether or not you work with us.