Why is my Snowflake bill so high, and how do I bring it down? · DpkDB
Why is my Snowflake bill so high, and how do I bring it down?
You pay for warehouse run time, not query work. Find where the credits go, fix auto-suspend and warehouse sizes, and add resource monitors before the next invoice.
The first Snowflake invoice arrives and it's three times the estimate. Nobody ran anything unusual. Where did the credits go?
In Snowflake you pay mainly for compute time, meaning how long virtual warehouses run, not how much work queries do. Most surprise bills come from warehouses that run when they don't need to, or are bigger than they need to be.
How compute is billed
A virtual warehouse consumes credits for every second it's running, with a 60-second minimum each time it resumes.
Each size step doubles the rate: X-Small is 1 credit/hour, Small 2, Medium 4, Large 8, and so on up to 6X-Large.
A warehouse bills whether it's running one query, twenty, or none. Only a suspended warehouse is free.
Find out where the credits went
-- Credits by warehouse, last 30 daysSELECT warehouse_name, SUM(credits_used) AS credits
FROM snowflake.account_usage.warehouse_metering_history
WHERE start_time >= DATEADD(day, -30, CURRENT_TIMESTAMP())
GROUPBY1ORDERBY2DESC;
-- Most expensive queries (elapsed time is the best proxy for cost on a busy warehouse)SELECT query_id, user_name, warehouse_name, warehouse_size,
total_elapsed_time /1000AS seconds, bytes_scanned, LEFT(query_text, 120)
FROM snowflake.account_usage.query_history
start_time DATEADD(, , ())
total_elapsed_time LIMIT ;
WHERE
>=
day
-7
CURRENT_TIMESTAMP
ORDER
BY
DESC
50
Also check metering_daily_history for serverless costs (automatic clustering, Snowpipe, materialized views, search optimization and so on), which run outside your warehouses.
The usual culprits and fixes
1. Auto-suspend set too long. A warehouse with AUTO_SUSPEND = 600 stays up, and bills, for 10 minutes after the last query. For BI and ad-hoc warehouses, 60 seconds is usually right:
ALTER WAREHOUSE bi_wh SET AUTO_SUSPEND =60 AUTO_RESUME =TRUE;
(Very short values on warehouses with frequent tiny queries can lose the local disk cache and hit the 60-second minimum repeatedly, so tune per workload.)
2. Something keeps waking it up. Dashboards refreshing every minute, a health check running SELECT 1, a scheduled job every 5 minutes: each one keeps a warehouse awake around the clock. Check query_history for small, frequent queries. Reduce refresh rates, lean on the result cache (repeated identical queries within 24 hours return from cache without a warehouse), or move trivial checks elsewhere.
3. Oversized warehouses. Bigger doesn't mean more efficient. If a query runs 2× faster on a Medium than on a Small, it costs the same. If it's only 1.2× faster, you're overpaying. Start small and size up only for queries that spill to disk (bytes_spilled_to_local_storage / remote_storage in the query profile) or that need to finish faster.
4. Too many warehouses, or too few. Separate warehouses per workload (ELT, BI, data science) make costs visible and stop one team's jobs from slowing another's, but each idle-yet-awake warehouse costs money. For concurrency spikes, use multi-cluster warehouses (MIN_CLUSTER_COUNT = 1) instead of permanently larger ones.
5. Queries that scan everything.SELECT * on wide tables, and filters that can't prune micro-partitions (for example wrapping the filter column in a function), make every query read more. Filter on columns that match the table's natural load order, or add a clustering key on very large tables that are always filtered by the same column. Automatic clustering has its own serverless cost, so justify it first.
6. Storage surprises. Long Time Travel retention on tables that are rewritten constantly (full reloads) keeps many copies. Use transient tables for staging, and short retention where recovery doesn't matter.
Put guardrails in place
CREATE RESOURCE MONITOR monthly_cap WITH CREDIT_QUOTA =500
FREQUENCY = MONTHLY START_TIMESTAMP = IMMEDIATELY
TRIGGERS ON80PERCENT DO NOTIFY
ON100PERCENT DO SUSPEND;
ALTER WAREHOUSE bi_wh SET RESOURCE_MONITOR = monthly_cap;
Also set STATEMENT_TIMEOUT_IN_SECONDS on warehouses so a runaway query can't run for hours.
Checklist
You pay for warehouse run time: 60-second minimum per resume, and each size doubles the rate.
Find heavy warehouses and queries in ACCOUNT_USAGE.
Set auto-suspend to about 60 seconds, stop needless wake-ups, and right-size warehouses.
Prune scans, watch serverless and Time Travel costs, and add resource monitors and timeouts.