Terraform Cost Visibility: Enforce Cloud Spend Guardrails at Plan Time
The Problem With Chasing Costs After the Fact
Cloud billing surprises follow a predictable pattern: an engineer ships a change on Monday, the cost anomaly alert fires on Thursday, and by Friday someone is digging through CloudTrail logs trying to figure out which Terraform resource tripled the bill. By then the damage is done.
The root cause is a workflow gap. Infrastructure-as-code lives in Git, but cost feedback has traditionally lived in the billing console—a completely separate system, checked by a different team, days or weeks later. Terraform’s evolving cost visibility features close that gap by surfacing spend signals during the plan phase, before any resource is provisioned.
For platform teams already enforcing security and compliance policies at plan time, adding cost guardrails is the logical next step.
How Terraform Surfaces Cost Estimates
HCP Terraform (formerly Terraform Cloud) includes a built-in cost estimation step that runs automatically after terraform plan. For every resource being added, changed, or destroyed, it queries the provider’s published pricing API and produces a delta:
Cost estimation:
+ $47.45/mo (aws_db_instance.reporting)
~ $0.00/mo (aws_s3_bucket.assets, no charge change)
- ($12.20/mo) (aws_elasticache_cluster.cache, destroying)
Net change: +$35.25/mo
New monthly total: ~$1,842.00
This output appears inline in the run UI and, critically, in pull request checks when you’ve connected your VCS provider. A reviewer can see the cost delta without leaving GitHub or GitLab.
Estimates cover the most common billable resource types across AWS, Azure, and GCP—compute, managed databases, load balancers, storage, and NAT gateways, among others. Resources whose pricing depends on runtime factors (data transfer volume, Lambda invocations, API Gateway requests) are flagged as “unestimated” rather than silently omitted, so you know where your blind spots are.
Project-Level Budget Signals
Cost estimation at the run level is useful, but platform teams managing dozens of workspaces need a higher-level view. HCP Terraform’s project-level budget notifications address this by letting you attach a monthly spend threshold to a project—a logical grouping of workspaces that might correspond to a team, an application, or an environment.
When any workspace inside that project runs a plan, the estimate is rolled up against the project budget. If the projected spend would breach the threshold, the run can be flagged or blocked, and a notification fires to your configured channel (Slack, PagerDuty, email, or webhook).
This changes the conversation from reactive incident response to proactive gate: the pull request is the moment of accountability, not the billing dashboard.
Wiring Cost Gates into CI
Connecting HCP Terraform to your VCS is straightforward—you map a workspace to a repository path, and every push to a tracked branch triggers a speculative plan. The cost estimate is part of that plan output.
For teams that want hard enforcement rather than advisory warnings, Sentinel and OPA (Open Policy Agent) policies can act on the cost estimate data. Here is a minimal Sentinel policy that blocks any run increasing monthly cost by more than $500:
import "tfrun"
main = rule {
tfrun.cost_estimate.delta_monthly_cost < 500.00
}
And the equivalent in Rego for teams using OPA with Conftest:
package terraform.cost
deny[msg] {
delta := input.cost_estimate.delta_monthly_cost
delta > 500
msg := sprintf(
"Cost increase of $%.2f/mo exceeds $500 threshold",
[delta]
)
}
Either approach lets you encode budget rules as code—versionable, reviewable, and enforceable the same way your security policies are.
A Practical Rollout Strategy
Dropping hard cost gates on an existing team without warning is a good way to create frustration rather than accountability. A staged rollout works better:
Phase 1 — Visibility only (Week 1–2)
Enable cost estimation across all workspaces. Do nothing else. Let engineers see the delta in their PRs. The point is to build intuition: a db.r6g.2xlarge costs more than a db.r6g.large. This alone catches many sizing mistakes.
Phase 2 — Soft alerts (Week 3–4)
Configure project-level budget notifications to fire to a shared Slack channel when a run is projected to increase spend by more than a meaningful threshold (set this based on your actual spend baseline, not a round number). Treat these as informational—no PRs are blocked yet.
Phase 3 — Hard gates on high-risk workspaces (Month 2+)
Apply Sentinel or OPA policies to production workspaces only. Development and staging workspaces get softer limits or remain advisory. Engineers learn the system on lower-stakes changes before it affects their production deploys.
Where Estimates Fall Short
Cost estimation is not a billing guarantee. Several real-world factors can cause the actual invoice to diverge from the plan-time estimate:
- Data transfer costs are notoriously hard to estimate without knowing traffic patterns. A new cross-region RDS replica might show a small compute delta but generate significant egress charges depending on replication volume.
- Reserved Instance and Savings Plan coverage is not reflected. Your EC2 estimate will show on-demand pricing even if the instance will be covered by a commitment.
- Usage-based services (Lambda, SQS, API Gateway) are partially or fully excluded. A Lambda function with millions of invocations/day dwarfs its provisioned cost.
- Marketplace and third-party resources are skipped entirely.
Think of plan-time cost estimates the way you think of static analysis: they catch a class of problems early, but they are not a substitute for runtime observability. The goal is to prevent large, obvious overruns—not to replace your FinOps tooling.
Complementary Tools Worth Knowing
Infracost is the leading open-source alternative for teams not on HCP Terraform. It runs as a CLI or CI step against any Terraform plan file and produces a cost breakdown with a PR comment integration. It also supports custom pricing overrides for enterprise discount structures.
Cloud Custodian (now a CNCF project) operates post-deployment rather than at plan time, but it complements IaC cost gates well: where Terraform guards the create/update path, Custodian can detect and remediate drift—resources that exist but were never planned through your approved workflow.
Used together, the two tools give you defense in depth: prevent expensive resources from being created, and clean up resources that escaped governance.
The Shift-Left Argument for FinOps
Security teams have spent years making the case for shift-left: find vulnerabilities in code review rather than in production. The same logic applies to cloud costs, and the tooling has caught up.
When a cost delta appears in a pull request comment, it becomes part of the normal engineering conversation. A reviewer asking “do we really need io2 volumes here, or would gp3 cover this workload?” is a FinOps conversation that costs nothing and saves real money. The same conversation is impossible once the resource is running—at that point it’s an ops ticket, a redeployment, and possible downtime.
Terraform’s cost visibility features do not require a new process. They add signal to the process you already have.