gcpbigqueryanalyticscost-optimization

BigQuery cost: on-demand vs slots, and how to stop scanning terabytes

BigQuery on-demand bills ~$6.25/TB scanned; capacity bills for slots. Here's which model is cheaper for your query volume, and why partitioning and never SELECT * is the biggest saving on either.

The C3X Team··8 min read

Quick answer

BigQuery on-demand bills ~$6.25 per TB scanned (first 1 TB/month free); capacity (Editions) bills for slots — committed or autoscaling compute. On-demand is cheaper for sporadic querying; slots win for heavy, steady workloads. Either way, the biggest single saving is not scanning data you don't need: partition and cluster tables, and never SELECT * on a large table.

BigQuery's pricing is famously cheap to start and famously easy to blow up, because the default on-demand model charges by bytes scanned — a dimension that's invisible until a single careless query scans a few terabytes. The two decisions that control your bill are which compute model you're on and how much data each query touches.

The two compute models

  • On-demand: ~$6.25 per TB scanned, first 1 TB/month free. You pay per query, nothing when idle. Simple, and cheap until query volume grows.
  • Capacity (Editions): you buy slots — units of compute — as autoscaling or 1-to-3-year commitments. Queries draw from the slot pool, so cost tracks provisioned compute, not data volume.

Storage is separate and cheap: ~$0.02/GB-month active, ~$0.01/GB-month long-term (tables untouched for 90 days drop to the long-term rate automatically).

Which model is cheaper

It's a crossover, like most cost questions:

  • On-demand wins for sporadic, exploratory, or low-volume querying. A team running a few dashboards and ad-hoc queries rarely exceeds the free tier by much.
  • Slots win when query volume is high and steady. Once your on-demand bytes-scanned bill would exceed the cost of the slot capacity you'd reserve, committed slots are cheaper — and give predictable, flat spend.

The trap is staying on on-demand as you scale: a growing analytics team querying large tables can quietly run up thousands per month in bytes-scanned charges that a slot commitment would have flattened.

The biggest saving applies to both: scan less

Whatever model you're on, cost (or slot pressure) tracks bytes processed. The highest-leverage habits:

  1. Partition large tables (usually by date) so queries prune to the relevant range instead of scanning everything.
  2. Cluster on common filter columns so BigQuery skips irrelevant blocks.
  3. Never SELECT *. BigQuery is columnar — naming only the columns you need can cut bytes scanned by 10x on wide tables.
  4. Dry-run first. The dry-run flag reports bytes a query will scan before you run it, so expensive queries get caught in review.
  5. Expire staging data with table expiration so storage (and accidental scans) don't accumulate.

FAQ

How is BigQuery priced?

Two compute models. On-demand bills ~$6.25 per TB of data scanned by your queries (the first 1 TB/month is free). Capacity (BigQuery Editions) bills for slots — units of compute — either autoscaling or committed. Storage is separate: ~$0.02/GB-month for active and ~$0.01/GB-month for long-term storage.

Is BigQuery on-demand or capacity pricing cheaper?

On-demand is cheaper for sporadic or low-volume querying — you pay only for bytes scanned and nothing when idle. Capacity (slots) is cheaper for heavy, steady querying because a committed slot pool costs less than the equivalent bytes-scanned bill. The crossover is roughly when on-demand spend would exceed the cost of the slots you'd otherwise reserve.

Why is my BigQuery bill so high?

Almost always SELECT * and unpartitioned tables on the on-demand model. Because you pay per byte scanned, querying all columns of a large table — or scanning the whole table because it isn't partitioned or clustered — can scan terabytes per query. Selecting only needed columns and partitioning by date are the biggest savings.

What are BigQuery slots?

Slots are units of query-processing capacity. With BigQuery Editions you buy slot capacity (autoscaling or committed) instead of paying per byte scanned. Queries share the slot pool, so cost becomes a function of provisioned compute rather than data volume — predictable, and cheaper at high query volume.

How do I reduce BigQuery costs?

Partition and cluster large tables, never SELECT * (name the columns), preview with table metadata instead of queries, set table expiration on staging data, move cold tables to long-term storage automatically (untouched 90 days), and switch heavy steady workloads to committed slots. Use the dry-run flag to see bytes scanned before running.

How does C3X estimate BigQuery cost?

C3X prices a google_bigquery_dataset for its storage footprint, and treats query compute as usage-driven — model expected bytes scanned (on-demand) or slot commitment in c3x-usage.yml, since query cost depends on what you run, not the dataset definition alone.

What to do next

Storage is the predictable part of BigQuery; query compute is the part that surprises. C3X prices a google_bigquery_dataset for its storage footprint and lets you model query volume as usage, so you can compare on-demand bytes-scanned against a slot commitment before choosing. The quickstart gets you a breakdown in minutes.

Try C3X on your own Terraform

Free and open source. No API key required. One command to install, one command to estimate.