Skip to main content
Back to Blog

Snowflake Warehouse Right-Sizing: How to Stop Paying for Compute You Never Use

Tue Jun 16 202611 min readInsignyx Team
Snowflake Cost Optimization Data Engineering FinOps

When we audit a new Snowflake account, the single fastest dollar we find is almost never a clever query rewrite. It's a warehouse that's been running at Large or X-Large since the day someone created it "to be safe" — doing work that a Small would finish in roughly the same wall-clock time, at a quarter of the credit burn.

This is the warehouse right-sizing problem, and it's Leak #2 in our breakdown of why your Snowflake bill is so high. It deserves its own deep-dive because the fix is unusually low-risk: you're not rewriting SQL, changing schemas, or touching a single downstream dashboard. You're changing one number on a warehouse and watching the bill drop.

This post shows you exactly how to find the warehouses that are mis-sized — in both directions — using nothing but SNOWFLAKE.ACCOUNT_USAGE, and how to resize them without anyone noticing except your finance team.

Why warehouse size is the most expensive decision you forget about

Snowflake credits scale with warehouse size on a brutally simple curve. Each step up doubles the credit-per-hour rate:

Warehouse sizeCredits per hourRelative cost
X-Small11x
Small22x
Medium44x
Large88x
X-Large1616x
2X-Large3232x
3X-Large6464x
4X-Large128128x

The trap is that a bigger warehouse doesn't make most queries proportionally faster. Doubling the size doubles the compute (more nodes, more memory, more parallelism), so a query that's bottlenecked on a large scan or a heavy join may run roughly twice as fast. But a query that's small, that's bottlenecked on a single step, or that's mostly waiting — those run at almost the same speed on a Small as on an X-Large. You pay 8x the credits for a few seconds of improvement nobody asked for.

That asymmetry is the entire opportunity. Right-sizing isn't about finding the smallest possible warehouse — it's about finding the smallest warehouse that still completes the work without spilling to disk or missing a performance SLA. Get that right and a 30–50% compute reduction is a routine outcome, not an aggressive one.

The two ways a warehouse is mis-sized

There are exactly two failure modes, and you have to check for both before you touch anything.

Oversized is the common, expensive one: the warehouse is bigger than the workload needs. Queries finish fast, there's no memory pressure, and concurrency is low — you're paying for headroom you never use. This is where the savings live.

Undersized is the one that bites back: the warehouse is too small for its workload, so queries run out of memory and spill data to local or remote storage. Remote spilling can make a query 10x slower. If you blindly shrink a warehouse that's already spilling, you'll make performance worse and someone will (rightly) escalate.

The good news: ACCOUNT_USAGE tells you which is which, per warehouse, with no guesswork.

Bar chart comparing eight Snowflake warehouses by monthly credits consumed against the percentage of time each warehouse was actually busy running queries. Several large warehouses show high credit consumption but low busy time, flagged as oversized right-sizing candidates.

Step 1: Find oversized warehouses (where the money is)

Start by ranking warehouses by how much you spend on them versus how hard they actually work. This query pulls 30 days of credit consumption alongside the query profile for each warehouse — median runtime, how often queries spill, and how concurrent the workload really is.

WITH spend AS (
  SELECT
    warehouse_name,
    SUM(credits_used) AS credits_30d
  FROM snowflake.account_usage.warehouse_metering_history
  WHERE start_time >= DATEADD('day', -30, CURRENT_DATE())
  GROUP BY 1
),
profile AS (
  SELECT
    warehouse_name,
    COUNT(*)                                              AS query_count,
    MEDIAN(execution_time) / 1000                         AS median_exec_seconds,
    MAX(warehouse_size)                                   AS warehouse_size,
    SUM(CASE WHEN bytes_spilled_to_local_storage  > 0 THEN 1 ELSE 0 END) AS queries_spilled_local,
    SUM(CASE WHEN bytes_spilled_to_remote_storage > 0 THEN 1 ELSE 0 END) AS queries_spilled_remote
  FROM snowflake.account_usage.query_history
  WHERE start_time >= DATEADD('day', -30, CURRENT_DATE())
    AND warehouse_name IS NOT NULL
    AND execution_time > 0
  GROUP BY 1
)
SELECT
  s.warehouse_name,
  p.warehouse_size,
  s.credits_30d,
  p.query_count,
  p.median_exec_seconds,
  p.queries_spilled_local,
  p.queries_spilled_remote
FROM spend s
JOIN profile p ON s.warehouse_name = p.warehouse_name
ORDER BY s.credits_30d DESC;

Read the result like this. A warehouse that is Large or bigger, burning a meaningful share of your credits, with a low median execution time (queries finishing in a few seconds) and zero spilling, is an oversized candidate. It's doing small-warehouse work on big-warehouse hardware. Those are your first downsizing targets, ranked by credits_30d so you tackle the biggest dollars first.

The columns that matter: median_exec_seconds tells you whether the work is actually heavy, and the two queries_spilled_* counts tell you whether there's any memory pressure justifying the current size. If both spill counts are zero and queries are fast, the warehouse has nothing to lose by shrinking.

Step 2: Confirm the warehouse isn't quietly spilling

Before you downsize anything, run the spill check explicitly. Spilling is the single signal that says "this warehouse is already at or below the right size — do not shrink it." This query surfaces the warehouses and queries where memory pressure is real.

SELECT
  warehouse_name,
  warehouse_size,
  COUNT(*)                                            AS spilling_queries,
  ROUND(AVG(bytes_spilled_to_local_storage)  / POWER(1024, 3), 2) AS avg_local_spill_gb,
  ROUND(AVG(bytes_spilled_to_remote_storage) / POWER(1024, 3), 2) AS avg_remote_spill_gb,
  ROUND(SUM(bytes_spilled_to_remote_storage) / POWER(1024, 3), 2) AS total_remote_spill_gb
FROM snowflake.account_usage.query_history
WHERE start_time >= DATEADD('day', -30, CURRENT_DATE())
  AND warehouse_name IS NOT NULL
  AND (bytes_spilled_to_local_storage > 0 OR bytes_spilled_to_remote_storage > 0)
GROUP BY 1, 2
ORDER BY total_remote_spill_gb DESC;

Any warehouse showing up here with meaningful total_remote_spill_gb is undersized for at least part of its workload. Don't shrink these — and if remote spill is heavy, consider sizing up one step, or better, splitting the heavy queries onto their own warehouse so you're not paying big-warehouse rates for the whole workload just to satisfy a few memory-hungry jobs.

A warehouse that appears in neither this list nor with high concurrency, but does appear as Large+ in Step 1, is the clean right-sizing win: oversized, no memory pressure, safe to shrink.

A two-by-two decision matrix for Snowflake warehouse right-sizing. The horizontal axis is warehouse utilization from low to high, the vertical axis is memory spilling from none to heavy. The low-utilization, no-spill quadrant is labeled downsize, the high-spill quadrant is labeled size up or split workload, and the balanced quadrant is labeled leave it.

Step 3: Quantify the dollars before you change anything

Right-sizing is easy to sell to stakeholders when you can put a number on it. Because each size step is a clean 2x, downsizing a warehouse by one size cuts its compute roughly in half — assuming runtime stays flat, which for oversized warehouses it largely does. This query estimates the monthly credit savings of dropping each warehouse one size.

WITH wh_spend AS (
  SELECT
    warehouse_name,
    SUM(credits_used) AS credits_30d
  FROM snowflake.account_usage.warehouse_metering_history
  WHERE start_time >= DATEADD('day', -30, CURRENT_DATE())
  GROUP BY 1
)
SELECT
  warehouse_name,
  credits_30d,
  ROUND(credits_30d / 2, 1)              AS credits_if_one_size_smaller,
  ROUND(credits_30d / 2, 1)              AS estimated_monthly_credit_savings,
  ROUND(credits_30d / 2 * 3.00, 2)       AS estimated_monthly_dollar_savings_at_3usd
FROM wh_spend
ORDER BY credits_30d DESC;

Swap the 3.00 for your actual effective credit price (Standard, Enterprise, and Business Critical editions differ, and your contract rate may differ again). The output gives you a ranked, dollarized list of right-sizing opportunities you can take straight into a planning conversation. Pair it with our Snowflake cost calculator if you want to model a few scenarios before committing.

How to actually resize a warehouse safely

The change itself is one statement:

ALTER WAREHOUSE analytics_wh SET WAREHOUSE_SIZE = 'SMALL';

It takes effect immediately and is fully reversible — no rebuild, no downtime, no data movement. That's what makes right-sizing the lowest-risk lever in Snowflake cost optimization. But run it through a short, disciplined process rather than eyeballing it:

First, resize one step at a time. Go from X-Large to Large, not X-Large to Small. The whole point is to find the floor without falling through it, and one step halves the cost already.

Second, watch for new spilling after the change. Re-run the Step 2 spill query against the day or two following each resize. If remote spill appears where there was none, you've gone one step too far — step back up. Local spill in small amounts is usually acceptable; remote spill is the line you don't cross.

Third, separate workloads instead of sizing for the worst case. The most common reason a warehouse is oversized is that it serves a mix — light BI dashboards plus one nightly heavy transform — and it was sized for the transform. Move the heavy job to its own warehouse, size that one appropriately, and let the dashboards run on a Small. You stop paying X-Large rates around the clock for a job that runs twenty minutes a night.

Fourth, use multi-cluster for concurrency, not a bigger size. If queries are queuing (check queued_overload_time in QUERY_HISTORY, or avg_queued_load in WAREHOUSE_LOAD_HISTORY), the problem is too many concurrent queries, not queries that are individually too big. Sizing up burns credits without fixing the queue. A multi-cluster warehouse that scales out and back in handles the concurrency at far lower cost.

A before-and-after comparison of one warehouse's monthly compute cost. The before bar shows an X-Large warehouse at a high credit total; the after bar shows the same workload on a Large warehouse at roughly half the credits, with a callout noting median query time increased only marginally.

Where teams get right-sizing wrong

A few cautions, because right-sizing done carelessly can erode trust in the whole cost program.

Don't optimize for the smallest warehouse — optimize for the right one. The goal is the smallest size that meets the SLA, not the smallest size that runs. A query that takes 4 seconds instead of 3 on a downsized warehouse is a great trade; a critical pipeline that now spills to remote storage and runs 10x slower is not. Always check the spill query after a change.

Watch warehouses with bursty, infrequent heavy jobs. A warehouse that's idle most of the month but runs one enormous quarter-end job will look oversized in a 30-day median and undersized during that job. For these, separate the heavy job onto its own right-sized warehouse rather than shrinking the shared one.

Re-measure after you change query patterns. Right-sizing is not a one-time event. New pipelines, growing data volumes, and added concurrency all shift the right size over time. Re-run the Step 1 and Step 2 queries monthly — or have them alert you — so warehouses don't quietly drift back into oversized territory.

Account for the auto-suspend interaction. Right-sizing and idle-time control work together. A correctly-sized warehouse that still sits running idle between queries is only half-optimized — pair this work with aggressive AUTO_SUSPEND settings, which we cover in our pillar guide on Snowflake bill drivers.

Bottom line

Warehouse right-sizing is the highest-leverage, lowest-risk move in Snowflake cost optimization. The credit curve is a clean doubling, so every size you remove halves that warehouse's compute — and most warehouses are running at least one size too big "to be safe." Use the three queries above to rank oversized warehouses by dollars, confirm they aren't spilling, quantify the savings, then resize one step at a time while watching for new spill. Done methodically, a 30–50% compute reduction is a typical result, not an aggressive one — with zero changes to your queries, schemas, or dashboards.

If you'd rather have this done for you — every warehouse profiled, every safe resize identified and dollarized — that's exactly what we do in a free Snowflake cost assessment. We'll hand you a ranked right-sizing plan with the savings already calculated, and you decide what to act on.

---

This is part of our Snowflake cost-optimization series. Start with the pillar: Why Is Your Snowflake Bill So High? The 4 Biggest Leaks, or explore our Snowflake cost optimization services.

Follow Insignyx on LinkedIn

More on data, cloud & AI cost optimization.

Follow

More from June 16, 2026

Content coming soon

Related Articles

Content coming soon

We use cookies

We use cookies to improve your experience.