Chapter 11: Collaboration and Automation on GCP
Topic 74

Cost Estimation

CostFinOps

Infracost puts a price tag on a Terraform plan. It parses the resources a change would create or modify and posts a cost diff on the pull request, so a reviewer sees that this PR adds $340 a month before merging — not after the invoice. Cost becomes a line in code review, alongside the plan itself, at the moment the decision is still cheap to change.

On GCP it prices what it can read deterministically from the plan — a Compute Engine machine type, a Cloud SQL tier, a regional disk's size — but usage-based services need usage assumptions, and Infracost is honest that it cannot guess your traffic. Knowing the line between what it prices confidently and what it cannot is the whole skill in reading its output.

The PR Cost Diff

infracost breakdown and infracost diff run in CI against the plan and post a comment showing the monthly cost delta of the change. The cost becomes part of code review the same way the plan is: a reviewer sees the diff in dollars next to the diff in resources, and a change that quietly adds an expensive instance is caught before merge instead of on the next bill.

The step below runs after the plan, reads the plan JSON, and posts the delta as a pull-request comment. It sits in the same Cloud Build or GitHub Actions workflow that already produces the plan.

Infracost reading the plan JSON in CI
# after terraform plan -out=tfplan
terraform show -json tfplan > plan.json
infracost diff --path plan.json \
  --usage-file infracost-usage.yml      # ground usage-based services
# infracost comment posts the delta on the PR

Because Infracost reads the plan rather than the live cloud, it prices exactly the change under review. The usage file passed here is what lets it price the services a plan alone cannot, which is the next distinction.

Cost becomes a line in code review
plan
infracost diff
PR comment

What Infracost Can Price

Infracost prices resources whose cost is fixed by configuration rather than runtime usage: Compute Engine machine types, persistent-disk size, Cloud SQL instance tiers, GKE node pools. Anything whose monthly cost the plan fully determines — the machine is an n2-standard-4, the disk is 500 GB — it can put an accurate number on, because the price follows directly from the configuration with no traffic to guess.

These deterministic line items are where Infracost is most trustworthy. A reviewer can take the priced figure for a Compute instance or a Cloud SQL tier at close to face value, because nothing about the cost depends on how the resource gets used once it exists.

What It Cannot Price Without Help

Usage-based services are the other half, and there Infracost cannot guess. BigQuery bytes scanned, Cloud Run request-seconds, Cloud Storage egress, Pub/Sub message volume — the cost depends on traffic you have not run yet, so the plan alone says nothing about the bill. Infracost prices these only against a usage-assumptions file you supply, and without one it honestly reports the line item as usage-dependent rather than inventing a number.

This is a feature, not a gap. A tool that confidently priced a BigQuery query at zero because the plan shows no bytes would be worse than one that says "depends on usage." Infracost refusing to guess your traffic is what keeps its deterministic numbers credible.

The Usage File

An infracost-usage.yml lets you state assumptions — "this Cloud Run service handles 10 million requests a month," "this BigQuery dataset scans 2 TB" — so the usage-based estimates are grounded in something concrete. Supply it and those line items get a real number; omit it and they show as "monthly cost depends on usage." The usage file is how you turn an unknown into a defensible estimate.

Keep the usage file realistic and version it alongside the configuration. Its assumptions are the difference between a cost diff that covers the whole change and one that has holes wherever a usage-based service sits.

Where It Fits and Its Honest Limits

Infracost runs after plan in the same Cloud Build or GitHub Actions workflow, reading the plan JSON. It is advisory by default — it surfaces cost to reviewers rather than blocking merges — and you make it a gate only by wiring a threshold policy on top. Wire it as a hard gate without a sensible threshold and every minor infra PR gets blocked on cost noise, and the team learns to route around it. A green cost diff also means cheap, not correct: Infracost prices money, not blast radius, and a cheap change can still be wrong.

Read the diff as the reliable signal and treat the absolute total as a list-price upper bound. Infracost prices list rates and does not know your committed-use discounts, sustained-use discounts, or negotiated pricing, so the total overstates a discounted bill — but the delta between "before" and "after" is computed the same way on both sides, so the change in cost is the number to trust. One more limit: Infracost can only price what the plan resolves, so a machine type that shows as (known after apply) prices as unknown until the value is concrete.

Deterministic vs Usage-Based Pricing

Deterministic from the plan — Compute Engine machine types, persistent-disk size, Cloud SQL tiers, GKE node pools. The cost follows from the configuration, so Infracost prices it accurately with no extra input. Take these numbers near face value.

Usage-based, needs a usage file — BigQuery bytes scanned, Cloud Run request-seconds, Cloud Storage egress, Pub/Sub volume. The cost depends on traffic the plan cannot know, so Infracost prices it only against an infracost-usage.yml and otherwise reports it as usage-dependent.

Common Mistakes
  • Trusting Infracost's absolute monthly number as the real bill — it uses list pricing and does not know your committed-use or sustained-use discounts, so treat the diff, not the total, as the signal.
  • Expecting it to price BigQuery or Cloud Run accurately with no usage file — usage-based services show as usage-dependent until you supply assumptions.
  • Wiring Infracost as a hard merge gate without a sensible threshold — every minor infra PR gets blocked on cost noise and the team learns to ignore it.
  • Forgetting that Infracost reads the plan, so it cannot price a resource the plan does not fully resolve — a (known after apply) machine type prices as unknown.
  • Assuming a green cost diff means the change is safe — Infracost prices money, not correctness or blast radius, and a cheap change can still be wrong.
Best Practices
  • Run infracost diff in CI and post the cost delta as a pull-request comment so cost is reviewed alongside the plan.
  • Supply an infracost-usage.yml with realistic usage assumptions for BigQuery, Cloud Run, and other usage-based services so their estimates are grounded.
  • Read the cost diff as the reliable signal and treat the absolute total as a list-price upper bound, not the invoice.
  • Make Infracost advisory by default, adding a cost-threshold gate only where a hard ceiling genuinely matters.
  • Version the usage file alongside the configuration so its assumptions are reviewed and kept current with the infrastructure.
Comparable tools Infracost the tool itself, plan-time cost in CI HCP Terraform built-in cost estimation on runs GCP Pricing Calculator the manual analog Cloud Billing budgets the after-the-fact backstop

Knowledge Check

Which resource can Infracost price accurately straight from the plan, with no usage file?

  • A Compute Engine instance's machine type, whose cost is fixed by configuration
  • BigQuery bytes scanned per query, which the plan declares directly as a fixed monthly figure
  • Cloud Run request-seconds, since the plan pins the exact monthly request count for the service
  • Cloud Storage inter-region egress, whose monthly volume is fixed the moment the bucket exists

Why is the cost diff more trustworthy than the absolute monthly total?

  • The total uses list pricing and ignores committed-use and sustained-use discounts, while the diff applies the same list math on both sides
  • The diff includes your account's negotiated enterprise contract pricing and commitment discounts, while the absolute monthly total only ever uses public list rates
  • The total is rounded up to the nearest hundred dollars while the diff is reported to the exact cent
  • The diff queries your live billing account for real rates while the total only reads the plan

A BigQuery line item shows as "monthly cost depends on usage." What grounds it into a number?

  • An infracost-usage.yml stating realistic assumptions, like the bytes the dataset scans per month
  • Running terraform apply once so Infracost can read the real usage that the live dataset reports
  • Switching Infracost to read the project's live billing export instead of the generated plan
  • Pinning the google provider to an exact version so the usage-based price resolves deterministically

What is the risk of wiring Infracost as a hard merge gate without a sensible threshold?

  • Every minor infra PR gets blocked on cost noise, and the team learns to ignore or route around the check
  • Infracost silently stops reading the generated plan JSON and falls back to querying the project's live billing account
  • The infracost-usage.yml file is wiped from the branch on every blocked merge attempt
  • It forces every plan run to be re-executed as a full apply just to compute the cost gate

You got correct