If you eyeball pricing without ever looking at the code, you tend to discover surprisingly large gaps right before release. The safe pattern is to treat Terraform's plan output as your single source of truth and let Infracost evaluate the diff for you automatically.
This guide is grounded in Terraform's stable, official behaviour (the plan/show workflow) and organises Infracost so you can use it confidently in both real work and exam scenarios.
Cost estimates improve when you base them on a plan where variables, modules, and data sources are already resolved to concrete values, rather than reading HCL statically. In Terraform you generate a plan with terraform plan, then convert it to machine-readable JSON with terraform show -json. Handing that JSON to Infracost is the standard production pattern.
Treating the plan as your source of truth means conditional branches (count/for_each), default values, and provider resolutions are all baked in. You see the diff before apply and review it in the PR, so cost regressions get caught early.
| Aspect | terraform plan | terraform apply | Infracost |
|---|---|---|---|
| Input | HCL + variables + state (read-only) | Plan + external API calls | plan.json or HCL/state |
| Purpose | Compute the proposed changes | Apply the actual changes | Calculate / compare cost |
| Output | plan.out / plan.json | Real resource changes and state updates | Cost breakdown and diff (JSON, table, PR comment) |
| Exam takeaway | Unknown values get resolved by the plan | Cost estimation does not require apply | Passing plan.json improves accuracy |
Data flow from plan to Infracost
Dev
|
v
terraform plan ----> plan.out -- terraform show -json --> plan.json
|
v
Infracost breakdown
|
v
コスト明細/PRコメントMinimal local workflow
terraform init
terraform plan -out plan.out
terraform show -json plan.out > plan.json
INFRACOST_API_KEY=xxxxxxxx infracost breakdown --path plan.jsonInfracost is a CLI that calculates estimates by consulting each cloud provider's public price list. It can read HCL straight from a Terraform project directory, but for accuracy and reproducibility we recommend going through plan.json.
Integration is straightforward: set the API key as an environment variable and run breakdown against plan.json. In CI it's common to reuse the existing plan artefact and post the result as a PR comment.
Setup snippet
# APIキー設定(例)
export INFRACOST_API_KEY=xxxxxxxxxxxxxxxx
# 計画の作成とJSON化
terraform plan -out plan.out
terraform show -json plan.out > plan.json
# 見積もり
infracost breakdown --path plan.json --format table
# 複数パスをまとめる infracost.yml(任意)
# version: 0.1
# projects:
# - path: ./app
# - path: ./infra/networkUsage-based pricing (storage GB-month, request counts, data transfer, etc.) can't be nailed down from HCL alone. Feeding Infracost realistic usage values via a usage file improves accuracy dramatically.
Pass production-equivalent variables via var-file so sizes and instance counts are concrete at plan time. If count/for_each conditions or default values are ambiguous, unknown values leak through and estimates swing.
Example usage file and var-file
# infracost-usage.yml(例)
version: 0.1
resource_usage:
aws_s3_bucket.my_logs:
monthly_tier_1_requests: 2000000
storage_gb: 500
aws_lb.app:
new_connections: 10000000
active_connections: 2000
# terraform.tfvars(本番)
instance_type = "t3.large"
volume_size = 200
replicas = 3The production playbook is to surface the cost diff in the PR and gate any change that crosses a threshold. Persist the base branch's estimate and compare it against the feature branch.
You can build this with the official GitHub Action or with plain shell. Tune failure conditions to your org policy by absolute amount or percentage increase.
GitHub Actions example (essentials only)
name: Cost Diff
on: pull_request
jobs:
infracost:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Terraform Plan
run: |
terraform init
terraform plan -out plan.out
terraform show -json plan.out > plan.json
- name: Setup Infracost
uses: infracost/actions/setup@v2
- name: Generate Base (main)
if: github.event.pull_request.base.ref == 'main'
run: |
infracost breakdown --path plan.json --format json --out-file .infracost-base.json
- name: Cost Diff
env:
INFRACOST_API_KEY: ${{ secrets.INFRACOST_API_KEY }}
run: |
infracost breakdown --path plan.json --format json --out-file current.json
infracost diff --path current.json --compare-to .infracost-base.json --format table
# 例: しきい値チェック(単純化)
infracost diff --path current.json --compare-to .infracost-base.json --format json --out-file diff.json
python .github/scripts/fail_on_threshold.py diff.json 20 100 # 20%または100通貨単位超で失敗The Terraform exams care less about cost estimation itself than about the correctness and reproducibility of the plan that underpins it. The keys are: treat plan as your source of truth, minimise unknown values, and make variables and conditionals explicit.
Fundamentals like count/for_each, lifecycle, variable precedence, and reading plan output (distinguishing create/replace/destroy) translate directly into your accuracy when interpreting cost diffs.
Commands to produce plan.json (quick reference)
terraform plan -out plan.out
terraform show -json plan.out > plan.json
# これをInfracostに渡す
infracost breakdown --path plan.jsonWhen variables differ across workspaces or environments, planning with unintended defaults skews the estimate. Always specify a production-equivalent var-file, even in CI.
Misresolved provider aliases or module paths cause plan failures or extra unknown values. Reconcile your providers and required_providers blocks and audit dependencies with graph/console.
Diagnostic commands
terraform providers
terraform graph | dot -Tsvg > graph.svg
terraform console
# planの検証
terraform plan -out plan.out && terraform show -json plan.out | jq '.planned_values.root_module.resources[] | .type, .name'A classic case: the same module but with different sizes for dev and prod. Generate plan.json for each environment, run Infracost diff, and the increase/decrease rationale lands right in the PR.
Because you only swap the var-file against a single HCL codebase, this is easy to standardise as part of your review process.
Sample configuration and comparison run
# main.tf(抜粋)
variable "instance_type" {}
variable "replicas" { type = number }
resource "aws_instance" "app" {
count = var.replicas
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
}
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] }
}
# dev.tfvars
instance_type = "t3.micro"
replicas = 1
# prod.tfvars
instance_type = "t3.large"
replicas = 3
# 実行
terraform init
terraform plan -var-file=dev.tfvars -out dev.out && terraform show -json dev.out > dev.json
terraform plan -var-file=prod.tfvars -out prod.out && terraform show -json prod.out > prod.json
# 見積作成
infracost breakdown --path dev.json --format json --out-file dev.cost.json
infracost breakdown --path prod.json --format json --out-file prod.cost.json
# 差分
infracost diff --path prod.cost.json --compare-to dev.cost.json --format tablePro
問題 1
A team wants to review an accurate cost estimate and its diff during PR review. Which workflow most reproducibly yields an estimate that reflects how modules and variables resolve?
正解: A
Making plan.json (the JSON-serialised plan) your source of truth folds in module expansion and concrete variable values, giving you an accurate and reproducible estimate with no apply required. A usage file further sharpens accuracy. State alone, or workflows that require apply, don't meet the requirement.
What's the difference between pointing Infracost at an HCL directory versus passing plan.json?
Reading HCL directly is static analysis, so conditional branches and data source resolution don't always carry through, and you end up with more unknown values. plan.json contains the values Terraform actually resolved, which boosts both reproducibility and accuracy of your estimate.
How do I specify usage-based pricing?
Use a usage file such as infracost-usage.yml to provide realistic values for things like storage capacity and request counts. That pins down the "depends on usage" line items and prevents under- or over-estimation.
Can I get an accurate estimate without running apply?
Yes. Generate plan.json from terraform plan and terraform show -json, then run Infracost against it. You can review the cost diff with no apply required. apply is not a prerequisite for cost estimation.
Practice with certification-focused question sets
無料で問題を解いてみるNicheeLab Editorial Team
NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.
HCL Syntax: Terraform's Configuration Language (2026)
HCL2 fundamentals for Terraform — blocks, attributes, expres...
Terraform Authoring & Operations Pro: Complete Guide (2026)
Tactics for the Terraform Pro exam — module authoring, works...
Terraform Providers: Plugin Management Fundamentals (2026)
Provider mechanics — required_providers, versions, mirrors, ...
Terraform Resource Blocks: Declarative Infra Units (2026)
Resource block fundamentals — addresses, references, common ...
Terraform Data Sources: Read-Only External Data (2026)
Data source basics — declaration, refresh behavior, dependen...