
September 10, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Cloud bills often spike after a Terraform merge, not during planning. Infracost: Estimate Terraform Costs in CI closes that gap by turning each pull-request plan into a readable monthly cost diff before anyone approves the change. If you already run Terraform CI/CD with GitHub Actions or GitLab pipelines, adding cost feedback takes minutes and saves hours of FinOps cleanup later. This guide walks through setup, pipeline wiring, threshold gates, and the production mistakes I see on real infrastructure repos.
What is Infracost and why should Terraform run it in CI?
Infracost is an open-source CLI that reads Terraform plan output and estimates monthly cloud spend. It does not replace your cloud provider billing console. It gives engineers a fast, consistent preview at review time.
The workflow is straightforward. Terraform produces a binary plan file. Infracost converts that plan to JSON, looks up unit prices, and renders a diff: added cost, removed cost, and net monthly change. That output lands as a PR comment, a pipeline artefact, or a failing job when spend crosses a threshold.
On teams where I maintain GitLab CI pipelines for application and infrastructure repos, cost visibility was always an afterthought. Someone merged an RDS size bump or an extra NAT gateway. Finance noticed three weeks later. Infracost in CI moves that conversation to the pull request, where the change is cheap to revert.
Infracost supports AWS, Azure, Google Cloud, and dozens of SaaS resources through the Terraform provider ecosystem. It works with infrastructure as code with Terraform, OpenTofu, and Terragrunt wrappers. The CLI is free and open source. Cloud Dashboard and policy features add team management when you need central guardrails.
FinOps is not only a finance task. Engineers choose instance sizes, replica counts, and data transfer paths. Putting cost data beside the plan output makes trade-offs visible without opening a spreadsheet. That aligns with broader FinOps and cloud cost optimization practices your org may already track.
How do you install and configure Infracost for Terraform CI?
Start on a developer machine before you wire CI. You need Terraform (or OpenTofu), the Infracost CLI, and a registered API key from the Infracost Cloud dashboard or self-hosted setup.
Install the CLI on Linux or macOS
Official install scripts pin a release. On Ubuntu 22.04 or 24.04—the same base I use for production runners—run:
curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh
infracost --version Register once per environment:
infracost register This stores an API key in ~/.config/infracost/credentials.yml. In CI, inject the key from a secret store instead of committing it. Treat it like any other credential you protect with secrets scanning in Git and CI.
Generate a plan file Infracost can parse
Infracost needs a saved plan, not just console output. From your Terraform root module:
terraform init -input=false
terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > plan.json
infracost breakdown --path plan.json For directory-based runs without a saved plan:
infracost breakdown --path . The breakdown command prints total monthly cost and per-resource lines. Use infracost diff when you have a baseline branch to compare against. That diff is what you want on pull requests.
Configure currency and usage assumptions
Default currency is USD. Set NPR-friendly reporting by passing --currency NPR where supported, or post-process for finance teams that think in rupees. Usage-based resources—S3 egress, Lambda invocations, CloudWatch logs—need a infracost-usage.yml file with realistic quantities. Without usage files, Infracost assumes minimal defaults and under-estimates variable spend.
version: 0.1
resource_usage:
aws_lambda_function.my_fn:
monthly_requests: 500000
request_duration_ms: 120
aws_cloudwatch_log_group.app:
storage_gb: 30
monthly_data_ingested_gb: 15 Commit usage templates per environment. Update them when traffic patterns change. Pair this with Terraform workspaces and environments so staging assumptions do not mask production scale.
How do you integrate Infracost with GitHub Actions or GitLab CI?
CI integration follows the same four steps: checkout, init, plan, infracost. The official GitHub Action wraps comment posting and S3 cache for baseline plans. GitLab CI uses a shell job with artefacts—similar to pipelines I run for Laravel deploys, but with Terraform state backends instead of Composer.
GitHub Actions example
Add a job that runs on pull requests targeting your default branch. Store INFRACOST_API_KEY in GitHub Actions secrets. Official docs live at Infracost GitHub Actions integration.
name: Terraform cost estimate
on:
pull_request:
paths:
- 'infra/**'
- '.github/workflows/terraform-cost.yml'
jobs:
infracost:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.0
- name: Terraform init and plan
working-directory: infra/prod
run: |
terraform init -input=false
terraform plan -out=tfplan.binary -input=false
terraform show -json tfplan.binary > plan.json
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- uses: infracost/actions/setup@v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Post Infracost comment
run: |
infracost comment github --path infra/prod/plan.json \
--repo ${{ github.repository }} \
--pull-request ${{ github.event.pull_request.number }} \
--github-token ${{ secrets.GITHUB_TOKEN }} \
--behavior update The --behavior update flag replaces an existing bot comment instead of spamming the thread. That small detail keeps PRs readable on active repos.
GitLab CI example
GitLab fits teams already using GitLab CI pipelines for application deploys. Add a stage before apply:
stages:
- validate
- plan
- cost
- apply
terraform-plan:
stage: plan
image:
name: hashicorp/terraform:1.9
entrypoint: [""]
script:
- cd infra/staging
- terraform init -input=false
- terraform plan -out=tfplan.binary -input=false
- terraform show -json tfplan.binary > plan.json
artifacts:
paths:
- infra/staging/plan.json
expire_in: 1 week
infracost-diff:
stage: cost
image: infracost/infracost:ci-0.10
needs: [terraform-plan]
script:
- infracost breakdown --path infra/staging/plan.json --format json --out-file infracost.json
- infracost output --path infracost.json --format table
- infracost diff --path infra/staging/plan.json --compare-to main
variables:
INFRACOST_API_KEY: $INFRACOST_API_KEY For Azure DevOps users, the same plan-json pattern applies inside Terraform with Azure DevOps Pipelines. Swap the comment helper for the Azure DevOps extension or publish artefacts to a cost dashboard.
State, credentials, and remote backends
CI plans fail silently when state backends are misconfigured. Confirm your runner can reach S3, Azure Blob, or Terraform Cloud. Lock files must be committed. Partial backend config belongs in CI variables, not in git. Read how to manage Terraform state safely before you automate cost gates on production paths.
How do you set cost thresholds and policy gates in CI?
Visibility alone helps mature teams. Regulated or budget-sensitive orgs often need hard stops. Infracost supports percentage and absolute monthly diff thresholds through CLI flags and Cloud Policy features.
CLI threshold on pull requests
Fail the job when monthly increase exceeds a dollar limit:
infracost diff --path plan.json \
--compare-to infracost-base.json \
--format json > diff.json
TOTAL=$(jq '.diffTotalMonthlyCost | tonumber' diff.json)
LIMIT=100
if awk "BEGIN {exit !($TOTAL > $LIMIT)}"; then
echo "Monthly cost increase $TOTAL exceeds limit $LIMIT"
exit 1
fi That pattern mirrors code coverage gates in CI. Treat cost like any other quality metric with a defined pass line.
Infracost Cloud Policy
Cloud Policy centralises rules: block any EC2 instance larger than a threshold, flag resources without tags, or require approval when diff exceeds Rs 50,000/month (~USD 375). Policies run in CI through the same API key and report pass/fail in the dashboard. For multi-account setups, see multi-cloud cost management and FinOps for how estimates fit beside real billing exports.
| Approach | Best for | Enforcement | Setup effort |
|---|---|---|---|
| PR comment only | Small teams, early adoption | Advisory | Low — one job |
| Shell threshold (jq/awk) | Single repo, fixed budget | Hard fail in CI | Low — ~10 lines |
| Infracost Cloud Policy | Many repos, tag rules, approvals | Central policy engine | Medium — dashboard config |
| Custom FinOps webhook | Existing chargeback systems | Varies | High — integration work |
Document override paths. Emergencies happen—a hotfix may need a larger instance for 48 hours. Require a finance or platform approver label when the gate fails instead of disabling the job permanently.
What are common Infracost CI mistakes and how do you fix them?
Most failures I troubleshoot are configuration gaps, not Infracost bugs. The CLI is only as accurate as the plan and usage data you feed it.
- Planning without remote state access. CI produces empty plans when credentials or backends are wrong. Cost shows zero change while production would change. Fix backend auth first; cost second.
- Skipping usage files on metered services. NAT gateways, Lambda, and log storage look cheap with defaults. Add
infracost-usage.ymlper environment and review quarterly. - Comparing against the wrong baseline. Use
--compare-towith a JSON snapshot from main, not stale artefacts. Regenerate baseline on each main merge. - Running only on apply branches. Cost feedback must run on pull requests. Post-merge comments arrive too late.
- Ignoring unsupported resources. Check the breakdown for "Unsupported" lines. Custom providers or new resource types may need upstream price entries or manual notes in the PR template.
- Treating estimates as invoices. Reserved instances, credits, and enterprise discounts are not in public list prices. Cross-check with Azure cost management or AWS Cost Explorer for budget sign-off.
Run Checkov scans on Terraform in the same pipeline. Security and cost failures often share root causes—oversized public resources, missing autoscaling, orphaned disks.
Keep a local repro command in your team wiki. Developers should run the same init, plan, and infracost steps CI runs. Paste output into PRs when estimates look off—that saves platform team round trips.
For JSON pipeline artefacts, a quick sanity check through the JSON formatter tool helps confirm diff structure before you write jq gates. Small utilities beat debugging escaped shell strings under pressure.
Key Takeaways
- Run Infracost on every Terraform pull request plan, not only on apply branches.
- Save plan JSON in CI, then call
infracost breakdownorinfracost diffwith a current main baseline. - Add
infracost-usage.ymlfor metered services so estimates reflect real traffic, not CLI defaults. - Start with advisory PR comments, then add shell or Cloud Policy gates once baselines are stable.
- Pair cost checks with security scans and safe remote state access—the same misconfigs cause both bill shock and risk.
- Treat Infracost numbers as directional previews; reconcile with provider billing before hard budget commitments.
People Also Ask
Does Infracost work with OpenTofu and Terragrunt?
Yes. Infracost reads Terraform plan JSON regardless of whether you generated it with OpenTofu or wrapped modules with Terragrunt. Point the CLI at the plan file or directory output. Provider support follows the Terraform registry resource types Infracost maintains in its price book.
How accurate are Infracost estimates compared to real cloud bills?
Estimates use public list prices and your usage assumptions. They exclude enterprise discounts, reserved capacity, free tiers beyond defaults, and tax. Use them to compare relative diffs between PRs, not to predict the exact NPR or USD invoice.
Can Infracost fail a CI pipeline when costs increase too much?
Yes. Parse infracost diff JSON with jq or awk and exit non-zero when the monthly delta exceeds your limit. Infracost Cloud Policy offers managed rules if you prefer dashboard-driven enforcement across many repositories.
Do you need Infracost Cloud for CI pull request comments?
You need a free API key for comment features and telemetry, but basic breakdown and diff commands run locally without a paid subscription. Cloud adds policies, dashboards, and team governance when your footprint grows beyond a single repo.
Ship Terraform changes with cost visibility built in
Infracost: Estimate Terraform Costs in CI turns infrastructure review into a finance-aware checkpoint without slowing developers down. Plan, diff, comment, gate—that sequence fits beside the pipelines you already maintain and catches the expensive surprises that used to surface only after merge.
If you want help wiring Terraform CI, FinOps guardrails, or production Linux and cloud administration for Nepal and remote teams, contact us with your repo layout and cloud targets. You can also browse the Adventure Third Pole Trek portfolio entry for an example of Laravel plus infrastructure work shipped end to end, or explore enterprise application development services when cost-aware IaC is part of a larger platform build.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

