Auto-Suspend & Billing Windows
22 min
Snowflake bills per-second while a warehouse is running — but a
warehouse doesn't suspend the instant a query finishes. It stays alive
for an auto_suspend_seconds grace period first, in case another
query arrives soon (avoiding the overhead of a full resume). If queries
are spaced closer together than that grace period, the warehouse never
actually suspends between them at all — the billed "running" period
merges into one continuous window instead of two separate ones.
def merged_running_windows(query_windows, auto_suspend_seconds):
windows = sorted(query_windows)
merged = []
for start, end in windows:
running_end = end + auto_suspend_seconds
if merged and start <= merged[-1][1]:
merged[-1] = (merged[-1][0], max(merged[-1][1], running_end))
else:
merged.append((start, running_end))
return merged
This is the exact same interval-merging pattern as GitHub's has_conflict overlap check and Model Deployment's rolling-progress logic -- 'merge windows that touch or overlap' is one of the most reusable patterns in this whole curriculum, showing up in scheduling, conflict detection, AND billing.
Write `merged_running_windows(query_windows, auto_suspend_seconds)`: each `(start, end)` in `query_windows` is a query's execution window. A warehouse stays running until `auto_suspend_seconds` after a query finishes; if another query starts before that running window ends, the warehouse never actually suspends, and the windows merge into one. Return the merged list of `(start, running_end)` windows, sorted by start time.
Why does a warehouse's AUTO-SUSPEND timer matter for cost, given that Snowflake bills per-second while a warehouse is actually running?
You can compute merged warehouse-running windows accounting for auto-suspend, and understand the tradeoff between minimizing idle billing and avoiding frequent resume overhead.