Start with attribution, not with optimisation
The instinct when a bill grows is to start tuning queries. That is the wrong first move, because it optimises whatever you happened to look at rather than whatever is actually expensive.
Every major cloud warehouse exposes query history with a cost or bytes-processed figure attached: information schema views in BigQuery, query history in Snowflake, system tables in Redshift. Pull a full month of it into a table you can group and sort. Until that exists, every conversation about cost is opinion.
Group the month three ways — by user or service account, by destination table, and by tag or label if your platform supports them. Almost every organisation finds the same shape: a small number of jobs account for most of the spend, and a meaningful share of those jobs feed something nobody reads.
- Bytes scanned or credits consumed, per query, for a full month.
- The identity that ran it: a person, a scheduler, a BI tool, or a reverse ETL job.
- The destination: which table, dashboard or downstream system consumed the result.
The four things that are usually paying for nothing
Once attribution exists, the same categories come up repeatedly. None of them are exotic, which is precisely why they survive: each one individually looks too small to be worth a ticket.
- Full-table rebuilds on a schedule, where an incremental model would process a fraction of the data. This is the single largest recurring line in most bills.
- Dashboards refreshing on a timer rather than on demand, including dashboards with no viewers at all. A report nobody opens still runs every hour.
- Development and test runs against production-sized data, because the sampling convention was never established.
- Retained raw data that is never queried after ingestion week, sitting in the storage class it landed in.
Connect cost to usage before deciding anything
Cost data alone tells you what is expensive. It does not tell you what is worth it. A model that costs a great deal and drives pricing decisions is fine; one that costs a tenth as much and feeds a dashboard with four views a quarter is not.
Most BI tools expose view counts per report and per user. Join that to the cost attribution and you get the only table that matters for this decision: cost per report against use per report. The cheap wins usually announce themselves immediately — expensive things at the bottom of the usage list.
Retire rather than optimise where the answer is obvious. Archiving an unused report is instant and permanent; tuning it is work that has to be maintained forever afterwards.
Fixes worth making, in order
With cost and usage side by side, the sequence is largely determined. Work top-down and stop when the remaining items cost less than the engineering time to address them — which happens sooner than most teams expect.
- Delete or archive what is unused. No engineering, immediate saving, no ongoing maintenance.
- Convert the largest scheduled full rebuilds to incremental models, starting with the most expensive.
- Reduce refresh frequency to match how the report is actually used. Daily decisions do not need hourly data.
- Partition and cluster the tables that dominate scan volume, so common filters stop reading everything.
- Move cold raw data to cheaper storage, once you have confirmed nothing queries it.
Then keep it from coming back
A cost audit that is not followed by a monitoring change is a one-off saving that decays over the following year. The mechanism matters less than the fact that someone sees the number regularly.
The lightweight version works: a scheduled query writing daily cost by model and by consumer into a table, one dashboard on top of it, and an alert when a model exceeds a threshold. That is a day of work and it makes the next increase visible in days rather than at the end of a quarter.
Adding a label or tag convention at the point where jobs are defined is the other half. Attribution is cheap to build in at creation time and expensive to reconstruct after the fact.