Snowflake Cost Management
Snowflake uses a pay-per-use pricing model. You pay for the compute power you use and the storage your data occupies. Understanding this billing model helps you control costs, avoid surprises on your invoice, and design efficient data workflows. This page explains exactly how credits work, what you get billed for, and how to manage costs effectively.
The Two Main Cost Categories
Every Snowflake bill breaks down into two primary costs:
- Compute costs: What you pay to run queries, load data, and execute any operation that uses a virtual warehouse
- Storage costs: What you pay to store your data, including table data, query result caches, and Fail-safe copies
Diagram: The Electricity Bill Analogy
Your electricity bill has two parts: a fixed monthly charge for being connected to the grid, and a variable charge for how much power you actually consumed. Snowflake storage is like the fixed grid connection charge — you pay based on how much data you store each month. Snowflake compute is like your power consumption — you pay only for what you actually use, and the meter stops when you turn off the lights (suspend the warehouse).
What Are Snowflake Credits?
A Snowflake Credit is the unit of compute currency. Every virtual warehouse consumes credits while it runs. The credit consumption rate depends on the warehouse size. The dollar value of a credit depends on your Snowflake contract (typically $2 to $4 per credit for on-demand pricing).
Credit Consumption by Warehouse Size
| Warehouse Size | Credits per Hour | Credits per Second | Relative Power |
|---|---|---|---|
| X-Small (XS) | 1 | 0.000278 | Baseline |
| Small (S) | 2 | 0.000556 | 2x XS |
| Medium (M) | 4 | 0.001111 | 4x XS |
| Large (L) | 8 | 0.002222 | 8x XS |
| X-Large (XL) | 16 | 0.004444 | 16x XS |
| 2X-Large (2XL) | 32 | 0.008889 | 32x XS |
| 3X-Large (3XL) | 64 | 0.017778 | 64x XS |
| 4X-Large (4XL) | 128 | 0.035556 | 128x XS |
Snowflake bills per second with a 60-second minimum. If a query runs for 10 seconds on an XS warehouse, you are charged for 60 seconds (the minimum). If it runs for 3 minutes, you pay for 3 minutes.
Warehouse Auto-Suspend and Auto-Resume
Diagram: The Hotel Room Key Card
A hotel room that is not occupied still costs money if the air conditioning, lights, and TV stay on. A smart hotel turns off everything automatically when no guest is present and restores it instantly when someone enters. Auto-Suspend works the same way: Snowflake turns off a warehouse that has been idle and turns it back on the moment a query arrives.
-- Create a warehouse with auto-suspend after 5 minutes of inactivity
CREATE OR REPLACE WAREHOUSE analytics_wh
WAREHOUSE_SIZE = 'MEDIUM'
AUTO_SUSPEND = 300 -- 300 seconds = 5 minutes
AUTO_RESUME = TRUE -- Automatically starts when a query arrives
INITIALLY_SUSPENDED = TRUE; -- Start in suspended state (don't pay until first query)
-- Modify an existing warehouse to add auto-suspend
ALTER WAREHOUSE reporting_wh SET AUTO_SUSPEND = 120; -- 2 minutes
-- Manually suspend a warehouse right now
ALTER WAREHOUSE reporting_wh SUSPEND;
-- Manually resume it
ALTER WAREHOUSE reporting_wh RESUME;Set AUTO_SUSPEND to the lowest acceptable value for your use case. For interactive query warehouses used by analysts, 5 minutes (300 seconds) is a common setting. For batch jobs that run once per hour, 60 seconds is appropriate.
Storage Costs
Storage in Snowflake is measured in terabytes per month. Snowflake compresses data automatically (often achieving 3x to 7x compression), so actual storage costs are typically much lower than the raw data size suggests.
Storage includes:
- Active data: Current table data stored in Snowflake
- Time Travel data: Historical versions of data kept for your configured retention period (default 1 day for Standard edition, up to 90 days for Enterprise)
- Fail-safe data: An additional 7-day window maintained by Snowflake for disaster recovery (cannot be controlled by users)
- Stage data: Files stored in internal Snowflake stages
- Query result cache: Cached query results (small but counted)
Checking Your Current Storage Usage
-- Storage usage across all databases
SELECT
database_name,
ROUND(average_database_bytes / 1024 / 1024 / 1024, 2) AS database_gb,
ROUND(average_failsafe_bytes / 1024 / 1024 / 1024, 2) AS failsafe_gb,
ROUND((average_database_bytes + average_failsafe_bytes) / 1024 / 1024 / 1024, 2) AS total_gb
FROM snowflake.account_usage.database_storage_usage_history
WHERE usage_date = CURRENT_DATE - 1
ORDER BY total_gb DESC;Understanding the Three Snowflake Pricing Editions
| Edition | Key Features | Time Travel | Credit Cost (Approximate) |
|---|---|---|---|
| Standard | Core features, basic security | Up to 1 day | Lowest |
| Enterprise | Multi-cluster warehouses, 90-day Time Travel, column-level security | Up to 90 days | Moderate |
| Business Critical | HIPAA compliance, SOC2 Type II, enhanced encryption, private link | Up to 90 days | Higher |
Resource Monitors: Preventing Cost Overruns
Resource Monitors let you set credit limits on warehouses or your entire account. When a limit is reached, Snowflake can notify you, suspend the warehouse, or both. This prevents unexpected costs from runaway queries or misconfigured jobs.
Diagram: The Spending Limit on a Debit Card
A debit card with a daily spending limit stops working once you hit the limit. You get an alert and no more charges go through until you act. A Resource Monitor works the same way: set a credit limit, define alert thresholds, and Snowflake enforces them automatically.
-- Create a resource monitor that limits a warehouse to 100 credits per month
CREATE OR REPLACE RESOURCE MONITOR monthly_analytics_limit
CREDIT_QUOTA = 100
FREQUENCY = MONTHLY
START_TIMESTAMP = IMMEDIATELY
TRIGGERS
ON 75 PERCENT DO NOTIFY -- Email alert at 75% usage
ON 90 PERCENT DO NOTIFY -- Another alert at 90%
ON 100 PERCENT DO SUSPEND; -- Suspend warehouse when limit reached
-- Apply the resource monitor to a specific warehouse
ALTER WAREHOUSE analytics_wh SET RESOURCE_MONITOR = monthly_analytics_limit;
-- Create an account-level resource monitor (covers all warehouses)
CREATE OR REPLACE RESOURCE MONITOR account_wide_limit
CREDIT_QUOTA = 500
FREQUENCY = MONTHLY
START_TIMESTAMP = IMMEDIATELY
TRIGGERS
ON 80 PERCENT DO NOTIFY
ON 100 PERCENT DO SUSPEND_IMMEDIATE; -- Stops everything immediately at 100%
ALTER ACCOUNT SET RESOURCE_MONITOR = account_wide_limit;Viewing Resource Monitor Status
SHOW RESOURCE MONITORS;
-- Check credit usage per warehouse
SELECT
warehouse_name,
credits_used,
credits_used_cloud_services
FROM snowflake.account_usage.warehouse_metering_history
WHERE start_time >= DATEADD(month, -1, CURRENT_TIMESTAMP)
ORDER BY credits_used DESC;Cloud Services Costs
Snowflake has a layer called the Cloud Services layer that handles metadata, authentication, query planning, and other management operations. This layer also consumes credits. Snowflake includes cloud services usage for free up to 10% of your daily compute consumption. Usage above 10% gets billed as additional credits.
Common activities that increase Cloud Services costs:
- Running many small
SHOWcommands or metadata queries - Very frequent small warehouse starts and stops
- Large numbers of very short queries (under 1 second each)
-- Check daily cloud services credit usage
SELECT
TO_DATE(start_time) AS usage_date,
ROUND(SUM(credits_used_cloud_services), 2) AS cloud_services_credits,
ROUND(SUM(credits_used_compute), 2) AS compute_credits,
ROUND(SUM(credits_used_cloud_services) / NULLIF(SUM(credits_used_compute), 0) * 100, 1) AS pct_cloud_services
FROM snowflake.account_usage.warehouse_metering_history
WHERE start_time >= DATEADD(day, -30, CURRENT_TIMESTAMP)
GROUP BY usage_date
ORDER BY usage_date DESC;Strategies to Reduce Snowflake Costs
Right-Size Your Warehouses
A common mistake is using a Large warehouse when an X-Small runs the same query in the same time. Always test queries on smaller warehouses first. If a query takes 60 seconds on XS and 30 seconds on Small, the XS is cheaper (less than half the cost for half the time savings). If a query takes 120 seconds on XS and 5 seconds on Large, the Large might save money due to dramatically shorter runtime.
Use Query Result Cache
Snowflake caches query results for 24 hours. If you run the same query twice within 24 hours and the underlying data has not changed, the second run returns instantly and uses zero compute credits. Design dashboards to hit the cache whenever possible.
-- Check if your query was served from cache
-- Look at the execution profile or query history
SELECT query_text, execution_status, query_type,
total_elapsed_time, bytes_scanned,
percentage_scanned_from_cache
FROM snowflake.account_usage.query_history
WHERE start_time >= DATEADD(hour, -24, CURRENT_TIMESTAMP)
ORDER BY start_time DESC
LIMIT 50;Set Time Travel Wisely
-- Reduce Time Travel for tables where you don't need history
-- This reduces storage costs significantly for large tables
ALTER TABLE large_event_log SET DATA_RETENTION_TIME_IN_DAYS = 1;
-- Set at the database level (applies to all new tables)
ALTER DATABASE raw_data_db SET DATA_RETENTION_TIME_IN_DAYS = 7;
-- Check current Time Travel retention per table
SELECT table_name, retention_time
FROM information_schema.tables
WHERE table_schema = 'PUBLIC'
ORDER BY retention_time DESC;Drop Unused Objects
-- Find tables that have not been queried in 90 days
SELECT
t.table_name,
t.table_schema,
ROUND(t.bytes / 1024 / 1024 / 1024, 2) AS size_gb,
MAX(qh.start_time) AS last_query_time
FROM information_schema.tables t
LEFT JOIN snowflake.account_usage.access_history ah
ON ah.objects_modified[0]['objectName'] = t.table_name
LEFT JOIN snowflake.account_usage.query_history qh
ON qh.query_id = ah.query_id
WHERE t.table_schema = 'PUBLIC'
GROUP BY 1, 2, 3
HAVING last_query_time < DATEADD(day, -90, CURRENT_TIMESTAMP)
OR last_query_time IS NULL
ORDER BY size_gb DESC;Use Clustering Keys on Very Large Tables
Clustering keys let Snowflake skip large portions of data during queries, dramatically reducing bytes scanned and therefore compute cost.
-- Add a clustering key on a commonly filtered column
ALTER TABLE orders CLUSTER BY (order_date);
-- Check clustering information
SELECT system$clustering_information('orders', '(order_date)');Viewing Your Bill and Usage
-- Total credit usage by day for the past 30 days
SELECT
TO_DATE(usage_date) AS date,
usage_type,
ROUND(credits_used, 2) AS credits
FROM snowflake.account_usage.metering_history
WHERE usage_date >= DATEADD(day, -30, CURRENT_DATE)
ORDER BY date DESC, credits DESC;
-- Credit usage by warehouse for the past 7 days
SELECT
warehouse_name,
ROUND(SUM(credits_used), 2) AS total_credits,
COUNT(*) AS query_count
FROM snowflake.account_usage.warehouse_metering_history
WHERE start_time >= DATEADD(day, -7, CURRENT_TIMESTAMP)
GROUP BY warehouse_name
ORDER BY total_credits DESC;Key Points Summary
- Snowflake costs come from two sources: compute credits (warehouses) and storage (data size).
- Credits are consumed per second with a 60-second minimum. Larger warehouses cost more credits per second but finish jobs faster.
- Auto-Suspend stops credit consumption when a warehouse is idle. Always set it to the lowest acceptable value.
- Resource Monitors enforce credit limits and send alerts to prevent unexpected bills.
- Cloud Services usage is free up to 10% of daily compute. Operations like excessive SHOW commands can push you over this limit.
- Query Result Cache serves repeated identical queries for free within 24 hours. Design workflows to leverage it.
- Reduce storage costs by setting shorter Time Travel retention periods on tables that do not need long history.
- Clustering keys on large tables reduce bytes scanned per query, directly reducing compute costs.
