Optimizing Snowflake costs without sacrificing performance
This guide focuses on Snowflake cost optimization for data engineers, analytics engineers, and Snowflake administrators responsible for designing and operating Snowflake workloads. It assumes familiarity with warehouses, tables, and query execution, and focuses on practical changes that directly reduce credit consumption.
Snowflake makes scaling analytics easy, but that same flexibility can quietly drive costs up if left unmanaged.
Most Snowflake spend is driven by three core factors:
- Compute: Virtual warehouses running queries, loading data, or performing transformations
- Storage: Active data, time travel, fail-safe, and historical micro-partitions
- Services: Metadata operations and background services (usually a smaller portion)

Among these, compute is almost always the dominant cost driver, especially when warehouses are oversized, idle, or running inefficient workloads.
To stay in control, Snowflake provides built-in cost visibility through the Cost Management views in the UI. From there, you can:
- Track credit usage over time
- Break down spend by warehouse
- Identify cost spikes and long-running workloads
- Set expectations and budgets with real data
Monitoring is the first step but real savings come from intentional design and configuration choices.
In this first blog post, we’ll dive into cost reduction strategies that fall into two main categories, virtual warehouse and table configuration.
In the second blog post, we’ll analyze how workload configuration, data loading patterns and built-in Snowflake controls can help reducing costs.
1. How to reduce Snowflake compute costs with virtual warehouse configuration
1.1 Optimize auto-suspend settings to reduce Snowflake costs
Compute is billed for every second a virtual warehouse runs, with a minimum charge of 60 seconds per start. Snowflake automatically suspends a virtual warehouse after a specified period of inactivity, with the default auto-suspend time set to 10 minutes (600 seconds).
When the auto-suspend value is set higher than 60 seconds, the warehouse continues running and incurring costs, even when it is not actively processing queries. Therefore, setting auto-suspend appropriately is critical for cost control.
For ETL and batch workloads, auto-suspend should typically be set to 60 seconds to minimize idle compute charges, while BI and interactive workloads benefit from 90–120 seconds to preserve cache and improve user experience. The most effective strategy is to separate ETL and BI into different warehouses with tailored auto-suspend settings to optimize both cost and performance.
Why auto-suspend below 60 seconds can cause double charges.
Setting auto-suspend below 60 seconds is not recommended, as it can unintentionally increase costs due to repeated minimum charges.Assume a warehouse has auto-suspend set to 30 seconds. A query runs for 10 seconds, after which the warehouse becomes idle and suspends at the 30-second mark. Even though the warehouse only ran for 30 seconds, Snowflake still charges for the full 60-second minimum. If another query arrives shortly afterward, the warehouse must resume, triggering another minimum 60-second charge. As a result, two short bursts of activity can lead to 120 seconds of billed compute, even though the warehouse was only actively used for a fraction of that time.
Best practice: Set auto-suspend to 60 seconds for ETL and batch workloads and to 90-120 seconds for BI and interactive workloads.
1.2. Right-size virtual warehouses
Over-sized virtual warehouses often account for a large share of Snowflake compute costs.
Because Snowflake pricing is based on execution time × credit consumption rate, a query that runs twice as fast on a Medium warehouse compared to a Small warehouse typically costs the same. However, once performance plateaus, larger warehouses simply increase cost without providing meaningful speed improvements. This behavior is illustrated in the graph below, where execution time flattens while cost continues to grow as warehouse size increases.

Recommended approach to determining the optimal warehouse size:
- Start with an X-Small warehouse whenever possible.
- Incrementally increase the warehouse size and monitor query duration.
- Stop scaling up when execution time no longer decreases proportionally (for example, no longer halves). This indicates the warehouse is no longer fully utilized.
- For the best cost-to-performance ratio, select one size smaller than the point of diminishing returns.
- Example: If increasing from Medium to Large only reduces query time by 25%, the Medium warehouse is typically the more cost-efficient choice.
- Use larger warehouses only when faster performance is explicitly required, keeping in mind that returns diminish beyond this point.
Best practice: Start small, scale up gradually, and stop when performance gains flatten. Choose the smallest size that meets requirements.
1.3. Set minimum cluster count to 1
In Snowflake Enterprise Edition and higher, multi-cluster warehouses allow additional clusters to be started in parallel to handle spikes in concurrency. To avoid unnecessary compute costs, the minimum cluster count should always be set to 1.
Snowflake automatically provisions additional clusters up to the configured maximum when workload demand increases, and does so with minimal startup time. Setting the minimum cluster count higher than 1 forces extra clusters to remain running even when they are not needed, resulting in unused but fully billable compute.
By keeping the minimum cluster count at 1, you ensure that additional clusters are only started when demand justifies them, preventing over-provisioning while still maintaining performance during peak usage.
Best practice: Always keep the minimum cluster count at 1 and let Snowflake scale up only when concurrency demands it.
1.4. Consolidate virtual warehouses
A common cost issue in Snowflake environments is warehouse sprawl. When too many warehouses exist, many are underutilized running infrequent queries or sitting idle, but still consuming credits. Cost efficiency improves when workloads are consolidated into as few warehouses as practical and those warehouses are kept busy.
Rather than creating warehouses by data domain (for example, separate warehouses for marketing and finance), it is typically more efficient to organize warehouses by workload type. For example, using one warehouse for data loading, one for transformations, and one for live BI or user-facing queries usually results in better utilization and lower overall cost.
Workloads within the same category often share similar performance characteristics. Data-loading jobs, for instance, generally tolerate some queueing and can often run efficiently on a shared, multi-cluster X-Small warehouse. In contrast, interactive or user-facing queries typically benefit from larger warehouses to minimize latency.
Best practice: Organize warehouses by workload type (loading, transformations, BI) rather than by team or domain.
2. How table configuration impacts Snowflake storage and query costs
2.1 Ensure tables are properly clustered
One of the most effective ways to optimize query performance and reduce costs is query pruning, which limits the number of micro-partitions scanned. Reading micro-partitions is one of the most expensive steps in Snowflake queries because it requires remote data access over the network.
Query pruning works when filters in WHERE clauses, joins, or subqueries can eliminate irrelevant micro-partitions. To make this effective, the table must be clustered on columns that match your query patterns, so each micro-partition contains a narrow range of relevant values. For an orders table where queries often filter by created_at, cluster the table on that column:
CREATE TABLE my_schema.my_table (
id NUMBER,
created_at TIMESTAMP_NTZ,
data VARIANT
)
CLUSTER BY (created_at);However, clustering is worth for tables that have a high ratio of queries to DML operations (INSERT/UPDATE/DELETE). This typically means that the table is queried frequently and updated infrequently. Before choosing to cluster a table, Snowflake strongly recommends that you test a representative set of queries on the table to establish some performance baselines.
Proper clustering reduces the data scanned per query, improving performance and lowering compute costs.
Best practice: Cluster on columns frequently used in filters or joins.
2.2 Drop unused tables
Unused tables and time-travel backups consume storage and contribute to Snowflake costs over time. Regularly identifying and removing tables that are no longer needed can help reduce credit usage.
How to identify unused tables
You can query Snowflake’s INFORMATION_SCHEMA.TABLES to find table’s structure changes (e.g., columns added, data types changed) or when data-modifying DML (INSERT, UPDATE, DELETE, MERGE) occurred.
SELECT table_schema,
table_name,
last_altered,
created
FROM information_schema.tables
ORDER BY last_altered ASC;If you want to identify tables that haven’t been queried recently, you need to use query history instead. For example, Snowflake’s QUERY_HISTORY view in the SNOWFLAKE.ACCOUNT_USAGE schema can tell you which tables were accessed and when.
Here’s a simple example:
SELECT DISTINCT
t.table_schema,
t.table_name,
MAX(q.start_time)AS last_query_time
FROM snowflake.account_usage.tables t
LEFT JOIN snowflake.account_usage.query_history q
ON q.query_text ILIKE'%'|| t.table_name||'%'
WHERE t.table_schema='YOUR_SCHEMA'
GROUP BY t.table_schema, t.table_name
ORDER BY last_query_timeCombining INFORMATION_SCHEMA.TABLES with query history gives the most accurate picture of unused tables.
Best practice: Combine metadata and query history to identify and safely remove unused tables.
2.3 Lower data retention (time travel)
Snowflake’s time-travel feature maintains copies of all changes to a table for a configured retention period, which increases storage usage and costs. The standard retention period is 1 day (24 hours) and is automatically enabled for all Snowflake accounts. A retention period of 0 days for an object effectively deactivates Time Travel for the object.
Reducing the time-travel retention period lowers storage consumption and associated Snowflake credits without impacting active workloads.
Time Travel can be set to 0 days on non-critical tables such as staging, intermediate, and development/sandbox tables, where data is transient and easily reproducible from source systems or pipelines. For production and business-critical tables, Time Travel should remain at the standard 1-day retention to protect against accidental deletes, bad merges, or other operational errors.
To lower the data retention period for a specific table:
alter table my_non_critical_table set data_retention_time_in_days=0;Best practice: Reduce retention periods for non-critical tables.
2.4. Use transient tables for non-critical data
Snowflake’s Fail-Safe feature is the final layer of data protection. Fail-Safe only becomes active after the time-travel retention period ends, lasts 7 days for permanent tables and cannot be configured.
For tables that are frequently deleted, re-created during ETL processes, or already backed up in external storage, maintaining Fail-Safe provides little value but increases storage costs.
By creating transient tables instead of permanent ones:
- Fail-Safe is not applied, reducing storage usage.
- Time-Travel costs can also be minimized.
This is ideal for intermediate or temporary ETL tables that don’t require full historical recovery.
Best practice: Use transient tables for intermediate or reproducible ETL data.
Conclusion
This post outlines practical Snowflake cost optimization techniques focused on virtual warehouse and table configuration, aimed at technical teams operating Snowflake in production. It shows how small, intentional configuration choices can significantly reduce credit consumption without impacting performance or reliability.
Key takeaways
- Compute is the primary cost driver in Snowflake, and most savings come from right-sizing warehouses, setting auto-suspend correctly, keeping minimum cluster count at 1, and consolidating warehouses by workload type.
- Table design directly impacts both performance and cost: proper clustering improves query pruning, while dropping unused tables, reducing time-travel retention, and using transient tables lowers unnecessary storage overhead.
- Monitoring alone is not enough — meaningful cost reduction requires aligning warehouse and table configuration with actual workload patterns and usage behavior.
In the next post, we will explore cost reduction techniques across three additional areas: workload configuration, data loading patterns, and leverage built-in Snowflake controls.
Do you want to understand where your Snowflake costs are really coming from?
We help technical teams review their Snowflake usage and identify concrete cost-saving opportunities without compromising performance or reliability. Get in touch with us here.
FAQ on Snowflake Cost Optimization
Snowflake costs are mainly driven by compute, storage, and cloud services usage. Compute from virtual warehouses is usually the largest cost factor, especially when warehouses are oversized or run unnecessarily long. Storage costs increase with time travel and fail-safe retention.
Reduce compute costs by right-sizing warehouses, setting auto-suspend to 60 seconds, and avoiding unnecessary job frequency. Incremental processing instead of full refreshes also lowers data scanned and execution time. Optimizing queries and consolidating warehouses further improves efficiency.
Yes, if configured correctly. Setting auto-suspend to 60 seconds prevents warehouses from running idle and consuming unnecessary credits. Settings below 60 seconds can increase costs due to repeated minimum billing charges.
Use transient tables for intermediate or reproducible data that does not require long-term recovery. They reduce storage costs because fail-safe does not apply. Avoid them for critical data that requires extended protection.
Clustering improves micro-partition pruning, which reduces the amount of data scanned during queries. Less data scanned means lower compute usage and faster execution. It is most effective for large tables frequently filtered on specific columns.
