Every morning, your team runs a straightforward dashboard refresh. This is simple stuff, maybe 200 queries. Then one month the invoice lands and you’re left staring at a line item three times larger than expected.
This has happened to many teams using BigQuery.
BigQuery’s pricing first appears elegant – pay for what you use, serverless, no infrastructure to manage – but in practice, its complex moving parts lead to a big gap between “what the team thought we’d pay” and “what we actually paid.”
This guide breaks down exactly how Google BigQuery costs work, what drives them up, and how to get them under control.
Note on pricing data: All figures referenced in this article are sourced from Google Cloud’s official BigQuery pricing documentation and reflect US multi-region rates as of March 23, 2026. Prices vary by region. Always verify current rates at cloud.google.com/bigquery/pricing before making final budget decisions.
How BigQuery Pricing Works
BigQuery charges across two primary cost centers:
- Compute: What it costs to process your queries
- Storage: What it costs to keep your data
These are billed independently, which is one of BigQuery’s architectural strengths because it means you don’t have to pay for a provisioned node that bundles both together. But that decoupling also means you’re left managing two separate levers.
There are two compute pricing models: on-demand and capacity-based (BigQuery Editions). A legacy flat-rate model was previously available but has been deprecated.
On-Demand Pricing
On-demand is BigQuery’s default pricing. You pay per terabyte (TiB) of data your queries scan. The first 1 TiB per month is free. After that, the rate is $6.25 per TiB in U.S. regions.
The benefits here are obvious:
- No commitment
- No setup
- You only pay when queries run
This setup is especially appealing for teams with light or unpredictable workloads.
The risk here is also clear: because billing is tied to bytes scanned instead of query count or runtime, a single poorly written query run against a large table can leave you with a shockingly large bill.
One widely-cited example in the BigQuery community involves a single SELECT * on a petabyte-scale table. At $6.25 per TiB, you’re looking at over $6,000 for a single query run.
On-demand pricing uses a shared pool of slots managed by BigQuery, with resources dynamically allocated based on demand.
Flat-Rate Pricing (Deprecated)
Google’s original alternative to on-demand was flat-rate pricing. This is a fixed monthly fee for a set number of slots, starting at $1,700 per month for 100 slots. This model has since been deprecated and replaced by the more flexible capacity pricing model built around BigQuery Editions.
If your team is still operating under a legacy flat-rate commitment, Google has migration paths available, but new purchases are no longer possible under this structure.
Capacity Pricing (BigQuery Editions)
Capacity pricing is the current alternative to on-demand. Instead of paying per TiB scanned, you reserve a pool of processing units called slots, units of computational capacity that BigQuery uses to execute queries. You pay for the slots you make available, regardless of how much data they process.
This model runs through BigQuery Editions, which comes in three tiers: Standard, Enterprise, and Enterprise Plus. Each tier provides additional levels of capabilities around auto-scaling, multi-region support, compliance features, and commitment discounts.
Here’s what that looks like in the U.S. region with pay-as-you-go:
| Edition | Pay-as-you-go (per slot-hour) |
| Standard | $0.04 |
| Enterprise | $0.06 |
| Enterprise Plus | $0.10 |
All three editions support autoscaling, allowing capacity to scale based on workload, though configuration and minimum capacity depend on the edition and setup. Enterprise and Enterprise Plus also support one-year commitments, offering about 20% savings, and three-year commitments, which offer about 40% savings.
Pro tip: The break-even point between on-demand and capacity pricing usually falls between 300 and 500 TiB of monthly processing, though this depends on your specific workload patterns.
What Influences Google BigQuery Costs
Understanding BigQuery’s billing mechanism is the first step. Knowing what actually drives a bill up is the place where most teams get in trouble.
Let’s break down the main drivers that lead to your bill ballooning throughout the month:
- Storage costs
- Importing data
- BigQuery API usage
- Processing
Storage Costs
Storage is usually the quiet cost driver. It doesn’t spike dramatically like a badly written query might but instead accumulates steadily and tends to get less scrutiny than compute.
There are a couple of primary cost drivers here: active storage costs and long-term storage costs.
Note: For all storage costs listed below, pricing varies by region and billing model (logical vs. physical).
Active Storage Costs
You’ll run into active storage with any table or table partition that’s been modified in the last 90 days. “Modified” meaning:
- Loading data
- Copying
- Streaming inserts
- Running DML statements (INSERT, UPDATE, DELETE)
- DDL operations
Querying your data does not count as modifying, so running queries on a table won’t reset or affect its storage tier.
There are two billing model options for storage, both set at the dataset level:
- Logical storage billing: This is the default mode that charges based on the uncompressed size of your data. Time travel and fail-safe storage are included in the base rate – you’re not billed separately for them.
- Physical storage billing: Charges are based on compressed bytes on disk. Because BigQuery’s columnar format compresses data efficiently, physical billing can be substantially cheaper – but it does bill separately for time travel and fail-safe storage, which can close the gap or even flip the comparison depending on how frequently your data changes.
If your team works with stable, append-mostly data, you’ll likely see the most meaningful savings by switching to physical billing. If your team has a high update frequency, then you’ll want to stay the course with the default mode.
Long-Term Storage Costs
Any table or partition that goes unmodified for 90 consecutive days automatically transitions to long-term storage – which is roughly half the active storage price. No action is required on your end. BigQuery handles this automatically. There’s also no performance, durability, or availability difference between active and long-term storage.
The 90-day timer resets to zero if any modification occurs. There’s a subtle implication worth noticing here: if you delete and recreate a table – which may happen during certain ETL patterns – the data starts the clock again at active storage rates.
Importing Data
Batch loading data from Cloud Storage or local files into BigQuery is free. That means no charges for ingesting data at rest. Cross-region load jobs are the exception. Those are billed under Google Cloud’s network data transfer pricing.
Streaming inserts that use the legacy streaming API are billed per byte. If you’re using the BigQuery Storage Write API, streaming costs are bundled differently, so it’s worth checking your specific integration to understand what applies.
BigQuery API Usage
The BigQuery Storage Read API is billed at $1.10 per TiB read. It supports high-throughput reads of table data. Standard query result access through the console, BigQuery API, or client libraries is not charged separately. You only pay the compute cost for the query itself.
Data export from BigQuery to Cloud Storage within the same region is free. Cross-region exports incur data transfer charges.
Processing Costs
On the compute side, the biggest cost driver is almost always query design. BigQuery uses columnar storage, so it reads only the columns your query references, not the entire row.
That means a query that selects two columns from a 100-column table only scans the data in those two columns. This is the single most powerful lever for controlling on-demand costs – and also the most commonly ignored one.
Other processing cost factors include:
- Table structure: Unpartitioned tables force full table scans, while partitioned tables allow BigQuery to skip entire date ranges or other partition keys based on your filter conditions.
- Clustering: BigQuery can prune blocks on clustered tables within a partition based on clustered column filters, further reducing bytes scanned.
- Query caching: BigQuery caches query results for 24 hours. Identical queries against unchanged tables are served from cache with no compute charge.
- Materialized views: Frequently run aggregations stored at materialized views can dramatically reduce compute by serving precomputed results instead of re-scanning raw data.
Google BigQuery Storage Costs by Data Type
The below pricing reflects U.S. multi-region rates from Google Cloud’s official documentation as of March 2026.
Cost of BigQuery Storage Per GB Per Month
The decision between logical and physical billing isn’t always straightforward: physical storage costs more per GB on the rate card, but because BigQuery compresses columnar data efficiently, the actual bytes on disk are often a fraction of the logical size.
Teams with high-compression data (structured, repetitive data like event logs or transaction records) tend to benefit from physical billing.
| Storage Type | Cost | Price Adjustments | Notes |
| Active Logical Storage | $0.02 per GB per month | First 10 GB free | n/a |
| Active Physical Storage | $0.04 per GB per month | First 10 GB free | Time travel and fail-safe storage billed separately at physical rate |
| Long-Term Logical Storage | $0.01 per GB per month | 50% reduction from active logical rates | Discount applied automatically after 90 days without modification |
| Long-Term Physical Storage | $0.02 per GB per month | 50% reduction from Active physical Storage | Time travel and fail-safe storage billed separately at active physical rates |
The best way to know for certain which type of billing is most efficient for your setup is to query INFORMATION_SCHEMA.TABLE_STORAGE for both logical and physical byte counts and compare the would-be costs directly.
Cost of BigQuery Storage Per TB Per Month
To scale, the above figures to terabyte-level planning:
| Storage Type | Cost |
| Active Logical Storage | $20 per TB per month |
| Active Physical Storage | $40 per TB per month |
| Long-Term Logical Storage | $10 per TB per month |
| Long-Term Physical Storage | $20 per TB per month |
Notice how, at scale, the differences between billing models become stark. A 500 TB data warehouse billed at active logical rates runs $10,000 per month in storage alone. If your data compresses at a 3:1 ratio under physical billing – which isn’t unusual for well-structured event data – actual physical bytes would be around 167 TB. And at $40 per TB, that’s roughly $6,700 per month.
That’s a $3,300 per month difference from billing model choice alone, before touching a single query.
How to Get Accurate Query Cost Projections
Knowing rates is useful, but knowing what your specific queries cost before they run is what actually lets you manage your BigQuery spend.
How to Get Query Costs
If you want to get accurate query costs before even running your query, you should use BigQuery’s query validator in the console. It shows the estimated bytes to be processed before execution. Any query that scans more than a safe threshold can be identified before it generates a charge.
You can also use the –dry_run flag via the bq command-line tool, or run the dryRun: true parameter in the BigQuery Jobs API. A dry run validates the query and returns the bytes estimate without executing it or incurring any costs.
You can also analyze queries after they have run with INFORMATION_SCHEMA.JOBS (or INFORMATION_SCHEMA.JOBS_BY_PROJECT for project-level views). This is your primary tool for historical cost analysis. This view exposes total_bytes_billed for each job, which you can convert to cost using the on-demand rate.
Here’s a practical query to identify your most expensive queries over the past 30 days:
SELECT
job_id,
user_email,
query,
ROUND(total_bytes_billed / POW(1024, 4), 4) AS tib_billed,
ROUND((total_bytes_billed / POW(1024, 4)) * 6.25, 2) AS estimated_cost_usd,
creation_time
FROM
`region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE
creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND job_type = 'QUERY'
AND state = 'DONE'
AND error_result IS NULL
ORDER BY
total_bytes_billed DESC
LIMIT 25;
NOTE: Replace region-us with your actual region or multi-region. The $6.25 multiplier reflects U.S. multi-region on-demand pricing as of March 2026. Adjust this if your team is in a different region or pricing model.
To go further – such as grouping by users or identifying repeated query patterns – you can extend this query:
SELECT
user_email,
COUNT(*) AS query_count,
SUM(total_bytes_billed) AS total_bytes,
ROUND(SUM(total_bytes_billed) / POW(1024, 4), 4) AS total_tib_billed,
ROUND((SUM(total_bytes_billed) / POW(1024, 4)) * 6.25, 2) AS total_estimated_cost_usd
FROM
`region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT
WHERE
creation_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
AND job_type = 'QUERY'
AND state = 'DONE'
AND error_result IS NULL
GROUP BY
user_email
ORDER BY
total_bytes DESC;
This surfaces which users or service accounts are driving the most spend – often the fastest path to finding optimization targets.
How to Estimate Storage Costs
For storage cost projections, the most reliable source is INFORMATION_SCHEMA.TABLE_STORAGE. This view provides current logical and physical byte counts per table, which you can use to model costs under either billing approach.
SELECT
table_schema AS dataset,
table_name,
ROUND(active_logical_bytes / POW(1024, 3), 2) AS active_logical_gb,
ROUND(long_term_logical_bytes / POW(1024, 3), 2) AS long_term_logical_gb,
ROUND(active_physical_bytes / POW(1024, 3), 2) AS active_physical_gb,
ROUND(long_term_physical_bytes / POW(1024, 3), 2) AS long_term_physical_gb,
-- Logical cost estimate
ROUND(
(active_logical_bytes / POW(1024, 3)) * 0.02 +
(long_term_logical_bytes / POW(1024, 3)) * 0.01,
4
) AS logical_cost_usd,
-- Physical cost estimate (excluding time travel / fail-safe for simplicity)
ROUND(
(active_physical_bytes / POW(1024, 3)) * 0.04 +
(long_term_physical_bytes / POW(1024, 3)) * 0.02,
4
) AS physical_cost_usd
FROM
`project_id`.`region-us`.INFORMATION_SCHEMA.TABLE_STORAGE
ORDER BY
active_logical_bytes DESC;
NOTE: Replace project_id and region-us with your actual values. Physical cost estimates here exclude time travel and fail-safe bytes for simplicity. For a complete comparison, also pull time_travel_physical_bytes and fail_safe_physical_bytes from the same view and apply active physical rates.
This gets you a table-by-table cost comparison between billing models. Run it across your production project, and you’ll quickly see which data sets are candidates for switching to physical billing – and which aren’t.
How to Optimize BigQuery Spend
A full BigQuery optimization deep-dive is entirely its own topic, but here are the highest-level strategies to start with:
- Stop using SELECT *: Selecting only the columns your query actually needs is the single fastest way to win on on-demand pricing. On a wide table, this can reduce scanned bytes, cutting your bill by 80-90%.
- Partition your tables: Date-partitioned tables let BigQuery skip partitions entirely when your query filters on the partition column. A query that filters to the last seven days on a three-year dataset can scan less than 1% of the data it would otherwise process.
- Cluster your tables: Clustering sorts data within partitions by one or more columns, allowing BigQuery to skip irrelevant blocks. Effective on high-cardinality filter columns like user_id or event_type.
- Use materialized views for repeated aggregations: If the same aggregation query runs dozens of times per day, a materialized view serves precomputed results at a fraction of the compute cost.
- Set max bytes billed limits: BigQuery lets you set a maximum_bytes_billed parameter per query. Queries that exceed the limit are rejected before incurring cost. This is an essential guardrail in shared environments.
- Evaluate your storage model: Run the INFORMATION_SCHEMA.TABLE_STORAGE analysis above to determine if physical billing makes sense for your highest-volume data sets.
- Move inactive data to long-term storage intentionally: While BigQuery handles this automatically after 90 days, understanding which data is approaching the threshold can help with cost forecasting.
- Consider capacity pricing if your workload is consistent: If you’re processing hundreds of TiB per month on a predictable schedule, the math on a slot reservation usually works out significantly better than on-demand.
BigQuery Costs Don’t Have to Be a Moving Target
The teams that get blindsided by BigQuery bills aren’t necessarily those that are running inefficient queries. They’re just operating without visibility. By the time an invoice arrives, the damage is already done.
The solution here isn’t optimization: it’s continuous monitoring that catches cost anomalies before they become expensive line items.
Be careful when evaluating BigQuery along with other tools like Snowflake so you fully understand which cost and performance structure best fits your organization.
No matter if your team is running on BigQuery, Snowflake, or another platform, the real problem is always the same: unpredictable costs and manual optimizations that require hours and hours of engineering time.
Yuki gives engineering managers and data platform teams a dev-free layer of continuous cost intelligence, helping to:
- Surface exactly where spending is going
- Flag anomalies before they hit the bill
- Automatically implement optimizations so your engineers can stay focused on what matters
The teams Yuki works with see an average of 37.6% in savings – all without making any changes to existing pipelines.
If you’re spending more than you expected on cloud data warehouse costs, reach out to Yuki for a free demo or free trial so you can see what your environment could look like with optimizations running on autopilot.


