Skip to content
All posts

Cost Per Query Is the Only Warehouse Metric Your CFO Should See

A short essay on the dashboard that should replace your FinOps slide.

June 16, 2026 by Yash 9 min read #FinOps#BigQuery#Snowflake#Databricks#CostPerQuery#CFOReporting

The CFO closed her laptop and asked, “So is the bill going up or down?”

The data lead said it was complicated.

She opened the laptop again.

The scenes in this post are drawn from the founder’s pre-Replatform consulting work — the cost-per-query metric is the point, not the engagement attribution.

The founder was in the room as the outside consultant on a prior engagement, ostensibly to present an audit. I had a slide ready that showed monthly Snowflake spend bucketed by warehouse, broken out by environment, with a red trend line going up and to the right. It was a good slide. I had spent two hours making it. She looked at it for maybe four seconds and asked the question above, and the data lead — a smart, conscientious engineer who had been at the company for three years — gave the only honest answer he could, which was that the bill was going up because the business was growing, but also some queries were getting more expensive, but also they had added new pipelines, but also the warehouse size had been bumped in March for a one-off backfill and never bumped back down.

She closed the laptop again. “I don’t know what to do with any of that.”

(The founder left that meeting thinking the slide was the problem. It took two more prior engagements to realise the slide was a symptom. The problem was that the team was reporting total spend to someone who can’t act on total spend. Total spend is a number a CFO can worry about. It is not a number she can change.)

This is a short essay about the metric I wish more warehouse teams reported instead.

The metric

Cost per query.

Specifically: cost per query, by workload class, trended weekly. Three numbers on one chart. Not seven. Not seventeen.

The reason it works is not that it is a cleverer metric than total spend. It is that total spend conflates three things — query volume, query efficiency, and pricing model — and cost per query separates them.

If your total bill went up 18% and cost per query is flat, you grew. Congratulations. Talk to the CFO about whether the growth is paying for itself; the warehouse is doing its job.

If your total bill went up 18% and cost per query is also up 18%, your queries are getting more expensive. That is an engineering problem, and the team can fix it.

If your total bill went up 18% and cost per query is down, you have two stories to tell — the queries are getting more efficient, but the business is growing faster than the efficiency, and the CFO can now see exactly which lever to pull.

The CFO does not need to understand slots, virtual warehouses, BigQuery editions, or auto-suspend. She needs to know which of those three sentences is true this month.

The unromantic definition

Cost per query is whatever you say it is, as long as the denominator is consistent. The version I use:

-- BigQuery, on-demand pricing version
SELECT
  DATE_TRUNC(DATE(creation_time), WEEK) AS week,
  CASE
    WHEN labels.value LIKE 'dashboard_%' THEN 'dashboard'
    WHEN labels.value LIKE 'pipeline_%' THEN 'pipeline'
    WHEN user_email LIKE '%@%.iam.gserviceaccount.com' THEN 'service'
    ELSE 'adhoc'
  END AS workload_class,
  COUNT(*) AS query_count,
  SUM(total_bytes_billed) / POW(1024, 4) AS tib_billed,
  SUM(total_bytes_billed) / POW(1024, 4) * 6.25 AS estimated_cost_usd,
  SAFE_DIVIDE(
    SUM(total_bytes_billed) / POW(1024, 4) * 6.25,
    COUNT(*)
  ) AS cost_per_query
FROM `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT,
     UNNEST(labels) AS labels
WHERE creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)
  AND job_type = 'QUERY'
  AND statement_type IN ('SELECT', 'MERGE')
GROUP BY week, workload_class
ORDER BY week DESC, workload_class;

A Snowflake version exists with query_history and warehouse_metering_history, joined on warehouse and time-bucketed; I’ll spare you the SQL and trust you can write it. Databricks needs a join across system.billing.usage and system.query.history which is messier but possible.

The point is not the SQL. The point is the workload class. Four buckets — dashboard, pipeline, service, adhoc — is enough to make the chart legible. More than four and your CFO stops reading.

What you’ll see on week one

Three things, every time:

The dashboard line will be the highest cost-per-query bucket. This will not feel right, because dashboards “feel” cheap, but every dashboard query reads more bytes than the equivalent pipeline query because pipelines are aggregated and dashboards are detail. The first time you see this you will want to argue with the chart. Don’t.

The pipeline line will be the lowest cost-per-query bucket but the highest total volume. This is fine. Pipelines are doing what they’re meant to do.

The adhoc line will be wildly noisy — one analyst running one bad query can move the weekly average by 40%. You will be tempted to filter out the adhoc bucket because it makes the chart ugly. Don’t filter it. The ugliness is the point. The adhoc bucket is where the early-warning lives — a sudden spike there is usually a new analyst learning the warehouse, and the cost of letting that spike compound for six weeks is way higher than the cost of a five-minute conversation in week one.

(On one prior engagement the founder watched a team’s adhoc cost-per-query 4x in a single week. Two days of investigation later: a data scientist had discovered cross-joins. He didn’t know they were expensive. Nobody had told him. He had a perfectly reasonable mental model in which a JOIN was a JOIN. After ten minutes of explanation the line came back down and stayed down. Total cost of the misunderstanding: several thousand dollars, rough estimate based on scan volume at the time. Total cost of the conversation: zero. The chart paid for itself many times over that week.)

The slide

Replace your FinOps slide with this:

Cost per query, last 12 weeks:

Dashboards: $0.34 → $0.29 (–15%) Pipelines: $0.04 → $0.04 (flat) Service: $0.18 → $0.21 (+17%) Adhoc: $0.11 → $0.09 (–18%)

Total spend: $94K → $108K (+15%) — query volume up 21%.

Cost per query — last 12 weeks, by workload classWeekly average cost per query (USD). Total spend annotation at bottom right.$0.00$0.10$0.20$0.30$0.40$0.50Wk 1Wk 3Wk 5Wk 7Wk 9Wk 11Wk 12Dashboards$0.34 → $0.29 (–15%)Pipelines$0.04 → $0.04 (flat)Service$0.18 → $0.21 (+17%)Adhoc$0.11 → $0.09 (–18%)$0.34$0.18$0.11$0.04Total spend: $94K → $108K (+15%) — query volume up 21%Period: last 12 weeks

The slide that should replace your FinOps deck — cost-per-query trended weekly, by dashboard.

That’s the whole slide. Five lines. The CFO now sees: spend went up, but cost per query went down across three of four classes, and the one that went up is the service-account class — which is operationally interesting and worth a follow-up. She can ask “what’s happening with service?” and you can answer it.

She cannot ask “what’s happening with my warehouse?” because that question has fifteen answers and she has six minutes.

(There’s a sibling metric on the cloud-platform side — cost per request, cost per tenant — worth tracking in parallel during any FinOps engagement, because warehouse savings that get eaten by compute or egress on the application side are not savings. They are a transfer. But that is a different essay.)

What the CFO should not see

Slots. Editions. Auto-suspend timers. Resource monitors. Virtual warehouse sizes. Reservation autoscaler floors. Idle compute percentage. Storage tier breakdowns. dbt model run times. Concurrency limits. Cold scan ratios. Spillage to remote storage.

All of these are operationally important. None of them belong on a CFO slide. If you find yourself on a Tuesday morning explaining the difference between BigQuery Editions Standard and Enterprise to a CFO, you have already lost the meeting — not because she can’t understand it, but because she will reasonably wonder why you’re explaining vendor pricing tiers instead of the line your spend is on.

The warehouse team’s job is to translate the operational world into one of those three sentences from earlier. We grew. We got more efficient. We got less efficient. That’s the contract. Everything else is for the engineering review, not the finance review.

The pattern beneath

Most data teams I meet are reporting total spend because total spend is what the billing console shows them. The billing console is built for the cloud vendor’s customer success motion, not for your CFO’s decision-making. It will happily tell you, in beautiful colour, that your spend has grown month over month. It will not tell you whether that growth is healthy or pathological.

This is the gap. And it’s the same gap that explains why so many “data team owns FinOps” initiatives die in their second quarter. The data team doesn’t have a metric the CFO can act on, so the conversation defaults to “the bill is up, what are you doing about it,” which puts the team in a defensive crouch, which means the team’s next quarter goes into vanity optimisations that move total spend by 4% instead of structural ones that move cost per query by 30%.

Cost per query is the lever the conversation should pivot around because cost per query is the only warehouse metric that has a direct engineering action attached to it. The dashboard line went up — which dashboard, who owns it, can we fix it. That conversation can happen in one Slack thread. Total spend going up doesn’t fit in a Slack thread.

(Most mid-market data teams don’t have a dedicated platform engineer to own a metric like cost per query end-to-end across the warehouse and the BI tool; that gap is real.)

The thing I’d do differently

The first time I built a cost-per-query dashboard for a client, I made it real-time. Fifteen-minute refresh against INFORMATION_SCHEMA. I was very proud of it. Nobody used it.

The CFO doesn’t want a real-time dashboard. She wants a Tuesday-morning email. The number doesn’t need to be live; it needs to be reliable. The version that gets opened is a daily-or-weekly digest, three lines long, sent to a small list of people who have agreed in advance what each direction of movement means.

That’s the second piece. Agreeing in advance. The first cost-per-query meeting with the CFO should not be a presentation of the metric; it should be a conversation that ends with three written sentences: if dashboard cost per query goes up by more than 10% week over week, we investigate. If pipeline cost per query goes up by more than 5%, we investigate. Everything else is information, not action.

Without those sentences, the metric is just another chart. With them, it’s a decision tool.

Closing

The CFO closed her laptop again, three months later, after seeing the new slide. She nodded once and said “ok, good.” That was the whole reaction. Five seconds of CFO attention, on a meeting that used to take twenty.

I’m not sure why this metric isn’t standard yet. Maybe it’s because the vendors prefer to sell total-spend dashboards because total spend is the number that grows. Maybe it’s because most data teams are run by engineers and engineers default to reporting the metrics that are interesting to engineers. Maybe it’s just that nobody has bothered to write down the obvious thing.

If you build it before the end of this quarter, the next time a CFO closes her laptop in your meeting, it’ll probably be because she got what she came for.

Related posts