Skip to content
All posts

Snowflake auto-suspend at 60s is right for half your warehouses

The math on matching auto-suspend to workload rhythm — and the anti-patterns that double your credits.

June 21, 2026 by Yash 6 min read #Snowflake#FinOps#DataEngineering#WarehouseOptimization#SQL

Snowflake bills on credit-seconds: a warehouse running but idle costs the same as a warehouse running and processing queries. The gap between “last query finished” and “warehouse suspended” is pure waste, and the default auto-suspend setting of 600 seconds (10 minutes) makes that waste structural across most accounts.

The counterargument is equally real. A warehouse suspended too aggressively introduces resume latency — typically 8-30 seconds for an XS or S warehouse — that breaks interactive dashboards and causes ETL jobs to queue behind each other during bursty load.

Both observations are correct. The answer is not one setting; it is different settings for different workload types, derived from query gap analysis on your actual QUERY_HISTORY.


The math on idle credits

A Snowflake X-Small warehouse consumes 1 credit per hour regardless of whether it is processing a query or sitting warm. On Enterprise pricing, 1 credit is approximately $3.00. A warehouse that runs 8 hours of active queries per day but stays warm for 16 hours costs $48/day — $24 in processing and $24 in idle heating. At 600s auto-suspend, the daily idle window is potentially much larger than it should be: if a warehouse runs its last query at 9pm but doesn’t suspend until 9:10pm, you have paid 10 minutes of credits for nothing. Over a fleet of 20 warehouses that pattern each has its own tail costs.

The savings opportunity is concentrated at the long tail of idle periods, not at the peaks. Reducing auto-suspend from 600s to 60s does not change anything during a busy query window; it only clips the idle tail after activity stops.

Warehouse credit cost at different idle patterns:
  20 warehouses × 10 min idle tail × $3/credit/hour × 30 days
= 20 × (10/60 h) × $3 × 30
= $300/month from idle tails alone

That is a low estimate. Production accounts with 30-50 warehouses and less disciplined suspend settings commonly see idle waste in the $1,500-4,000/month range — figures consistent with QUERY_HISTORY-based audits on mid-market Snowflake deployments. An India consumer commerce platform that ran this analysis across its warehouse fleet found approximately 70% of warehouse spend concentrated in a small number of warehouses running larger-than-needed sizes with permissive auto-suspend, and reduced warehouse spend by roughly 70% over the following quarter through sizing and suspend tuning. That kind of finding is not universal, but the pattern of concentration — a few oversized, under-suspended warehouses driving most of the cost — repeats consistently.


Analysing query gaps from QUERY_HISTORY

Before setting any warehouse to 60 seconds, run the gap analysis. A query gap is the time between one query finishing and the next query starting on the same warehouse. If all gaps are under 30 seconds, aggressive auto-suspend saves nothing (the warehouse won’t stay idle long enough to hit the threshold). If most gaps are over 5 minutes, a 60-second setting clips significant idle cost.

-- Snowflake: query gap distribution by warehouse
-- Run in SNOWFLAKE.ACCOUNT_USAGE (requires ACCOUNTADMIN or SYSADMIN)
WITH query_times AS (
  SELECT
    warehouse_name,
    start_time,
    end_time,
    LEAD(start_time) OVER (
      PARTITION BY warehouse_name
      ORDER BY start_time
    ) AS next_query_start
  FROM snowflake.account_usage.query_history
  WHERE start_time >= DATEADD('day', -14, CURRENT_TIMESTAMP())
    AND warehouse_name IS NOT NULL
    AND execution_status = 'SUCCESS'
),
gaps AS (
  SELECT
    warehouse_name,
    DATEDIFF('second', end_time, next_query_start) AS gap_seconds
  FROM query_times
  WHERE next_query_start IS NOT NULL
    AND gap_seconds > 0
)
SELECT
  warehouse_name,
  COUNT(*) AS total_gaps,
  PERCENTILE_CONT(0.50) WITHIN GROUP (ORDER BY gap_seconds) AS p50_gap_s,
  PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY gap_seconds) AS p75_gap_s,
  PERCENTILE_CONT(0.90) WITHIN GROUP (ORDER BY gap_seconds) AS p90_gap_s,
  PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY gap_seconds) AS p95_gap_s,
  COUNT_IF(gap_seconds < 60) AS gaps_under_60s,
  COUNT_IF(gap_seconds BETWEEN 60 AND 300) AS gaps_60_to_300s,
  COUNT_IF(gap_seconds > 300) AS gaps_over_300s
FROM gaps
GROUP BY 1
ORDER BY total_gaps DESC;

The p50 gap and the gaps_under_60s column tell you whether a 60-second setting will actually fire. If 80% of gaps are under 60 seconds (queries are arriving faster than the threshold), changing auto-suspend to 60 seconds changes nothing — the warehouse stays warm through query activity and auto-suspend only triggers at the true end of a session. If 60% of gaps are over 300 seconds, the current 600-second setting is costing you 300-600 seconds of idle credits on every inter-session gap.


Auto-suspend settings by workload type

Workload typeWorkload patternRecommended auto-suspendResume latency acceptable?
Interactive analytics / BI dashboardsFrequent queries during business hours, then idle for hours60sYes — users tolerate a few seconds per session start
Scheduled ETL (nightly batch)Long queries, clear start and end, no inter-query gaps needed60sYes — job orchestrator waits for warehouse on resume
Streaming micro-batch (runs every 60-300s)Continuous low-volume queries, very short inter-query gaps120-300sNo — resume latency would exceed batch interval
Data loading (Snowpipe or manual COPY INTO)Unpredictable arrival times, medium-long runs120sDepends on SLA
Dev / sandbox warehousesAd-hoc, infrequent, long gaps60s alwaysYes
Compute-heavy transforms (dbt production)Long-running, clustered during transform window60s after windowYes — next run is scheduled

The short version: 60 seconds is right for interactive warehouses and overnight ETL. It is wrong for micro-batch ingestion warehouses where resume latency compounds into pipeline lag.


The three multi-warehouse anti-patterns that double spend

Anti-pattern 1: One oversized warehouse for everything. A single 2XL warehouse is used for interactive BI, overnight ETL, and the data science team’s ad-hoc exploration. The BI team needs it warm during business hours (so auto-suspend can’t be aggressive); the ETL team needs high concurrency (so the size stays large). The data science team runs occasionally and holds the warehouse warm during long gaps between notebooks. The correct architecture is three separate warehouses — one XS for interactive, one M for ETL, one XS for data science — each with appropriate suspend settings. The combined cost of three appropriately sized warehouses is usually lower than the single oversized one.

Anti-pattern 2: Auto-suspend disabled on a “performance” warehouse. A warehouse is created for a critical reporting flow and marked AUTO_SUSPEND = 0 (disabled) by a well-meaning engineer who doesn’t want a CFO dashboard to wait on resume. The warehouse then runs 24/7 regardless of query activity. For a Large warehouse on Enterprise pricing, this adds approximately $2,160/month in unconditional cost (24h × 30d × 3 credits/hour × $3/credit). The correct fix is not disabling suspend — it is pre-warming the warehouse before the CFO’s scheduled report runs, using a scheduled ALTER WAREHOUSE ... RESUME statement before the dashboard refresh.

Anti-pattern 3: Many warehouses, all at the same size. Teams create warehouses for each team or each environment and set them all to XS or M based on convention rather than workload analysis. A warehouse running a SELECT COUNT(*) FROM ORDERS for a health check does not need the same size as a warehouse running a multi-TB window function aggregate. Size and suspend are related: an under-sized warehouse runs queries slowly (encouraging users to add more queries while waiting, keeping the warehouse warm for longer), while an appropriately sized warehouse finishes quickly (allowing the auto-suspend to fire sooner).


The Snowflake ALTER WAREHOUSE statement

Once you have the gap analysis and the right suspend value per warehouse, the change is a single SQL statement per warehouse:

-- For an interactive BI warehouse with long inter-session gaps:
ALTER WAREHOUSE bi_reporting_wh
  SET AUTO_SUSPEND = 60;       -- seconds

-- For a micro-batch ingestion warehouse where resume latency matters:
ALTER WAREHOUSE ingest_streaming_wh
  SET AUTO_SUSPEND = 180;

-- For dev/sandbox where idle cost is pure waste:
ALTER WAREHOUSE dev_sandbox_wh
  SET AUTO_SUSPEND = 60
  AUTO_RESUME = TRUE;

-- Verify the current setting:
SHOW WAREHOUSES LIKE '%';
-- Look for the AUTO_SUSPEND column in the result

These changes take effect immediately and do not interrupt running queries.


If you want a warehouse-by-warehouse breakdown of Snowflake spend including idle cost analysis and suspend recommendations, the FinOps Quick Check covers this as part of the initial Snowflake cost review.

Related posts