BlogCloud & Infrastructure
Cloud & Infrastructure

Shift-Left Cloud Costs with Infracost: See AWS Costs Before You Deploy

Infracost integrates with Terraform and CI/CD to show you the monthly cost impact of every infrastructure change β€” before it hits production. Pull request comments, policy enforcement, and cost forecasting bring FinOps directly into the engineering workflow.

P

Priya Sharma

Full-Stack Developer and open-source contributor with a passion for performance and developer experience.

April 13, 2026
18 min read

The Problem: Cost Surprises After Deployment

The traditional cloud cost workflow is backwards: engineers write Terraform, deploy to production, and discover the cost impact weeks later when the bill arrives. By then, the architecture is live, dependencies have formed, and changing it is expensive in both engineering time and migration risk.

Shift-left cost visibility flips this: show engineers the monthly cost delta of their pull request before they merge. A $2,000/month increase is easy to optimize when it's still in code review. It's much harder to address six weeks after deployment.

Infracost Setup

# Install Infracost CLI
brew install infracost  # macOS
# Or:
curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh

# Authenticate (free for open source, paid for teams)
infracost auth login

# Register for API key (free tier: unlimited OSS projects)
infracost configure set api_key YOUR_API_KEY

# Run against a Terraform project
cd /path/to/terraform
infracost breakdown --path .

# Output:
#  Name                                     Monthly Qty  Unit   Monthly Cost
#  aws_instance.web
#  β”œβ”€ Instance usage (Linux/UNIX, on-demand, m5.xlarge)   730  hours        $140.16
#  β”œβ”€ root_volume: General Purpose SSD storage (gp2)      50  GB              $5.00
#  └─ root_volume: Provisioned IOPS                        0  IOPS             $0.00
#  aws_rds_instance.main
#  └─ Database instance (Multi-AZ, db.r6g.2xlarge)       730  hours        $583.38
#  OVERALL TOTAL                                                            $728.54

GitHub Actions: Cost Comment on Every PR

# .github/workflows/infracost.yml
name: Infracost Cost Estimate

on:
  pull_request:
    paths:
      - '**.tf'
      - '**.tfvars'

jobs:
  infracost:
    name: Infracost PR Comment
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write

    steps:
      - name: Checkout PR branch
        uses: actions/checkout@v4

      - name: Setup Infracost
        uses: infracost/actions/setup@v3
        with:
          api-key: {{ secrets.INFRACOST_API_KEY }}}

      - name: Checkout base branch for comparison
        uses: actions/checkout@v4
        with:
          ref: {{ github.event.pull_request.base.ref }}}
          path: /tmp/base-branch

      - name: Generate cost estimate for base branch
        run: |
          infracost breakdown             --path /tmp/base-branch             --format json             --out-file /tmp/infracost-base.json             --terraform-var-file=terraform.tfvars

      - name: Generate cost estimate for PR branch
        run: |
          infracost breakdown             --path .             --format json             --out-file /tmp/infracost-pr.json             --terraform-var-file=terraform.tfvars

      - name: Post diff as PR comment
        run: |
          infracost diff             --path /tmp/infracost-pr.json             --compare-to /tmp/infracost-base.json             --format diff

      - name: Post cost comment to PR
        uses: infracost/actions/comment@v3
        with:
          path: /tmp/infracost-pr.json
          compare-to: /tmp/infracost-base.json
          behavior: update  # Update existing comment instead of creating new ones

Example PR Comment Output

## Infracost estimate

| Monthly cost change | Details |
|---------------------|---------|
| +$2,847/month       | 3 resources changed |

### Changed resources

aws_instance.web
  - instance_type: t3.small -> m5.2xlarge
  Monthly cost: $15.18 -> $280.32 (+$265.14/month)

aws_db_instance.main  
  - instance_class: db.t3.medium -> db.r6g.2xlarge
  Monthly cost: $48.91 -> $583.38 (+$534.47/month)

aws_elasticache_cluster.cache
  + NEW RESOURCE added
  Monthly cost: +$2,047.39/month (dax.r6g.4xlarge Γ— 3)

---
Previous total: $1,247.58/month
New total:      $4,094.44/month
Difference:     +$2,846.86/month (+228%)

@reviewer: This PR adds $2,847/month. Please confirm this is intentional.
Tip: Consider dax.r6g.large Γ— 3 ($374/month) to start.

Policy Enforcement with OPA (Open Policy Agent)

# infracost-policy.rego
# Block PRs that increase monthly cost by more than $500

package infracost

# Deny if monthly cost increase exceeds threshold
deny[msg] {
  baseline := input.projects[_].breakdown.totalMonthlyCost
  pr := input.projects[_].diff.totalMonthlyCost
  increase := pr - baseline
  increase > 500
  msg := sprintf(
    "Monthly cost increase of $%.2f exceeds the $500 limit. Requires FinOps team approval.",
    [increase]
  )
}

# Warn about expensive instance types
warn[msg] {
  resource := input.projects[_].breakdown.resources[_]
  resource.resourceType == "aws_instance"
  contains(resource.metadata.calls[_].arguments.instance_type, "x1e")
  msg := sprintf(
    "Resource %s uses x1e instance family (memory-optimized, high cost). Consider r6g.",
    [resource.name]
  )
}

# Block specific expensive instance families
deny[msg] {
  resource := input.projects[_].breakdown.resources[_]
  resource.resourceType == "aws_instance"
  instance_type := resource.metadata.calls[_].arguments.instance_type
  blocked := ["p4d", "p3dn", "x1e", "x2gd"]
  blocked[_] == split(instance_type, ".")[0]
  msg := sprintf(
    "Instance type %s is in the blocked list. Use p3 or g4dn for GPU, r6g for memory.",
    [instance_type]
  )
}
# Apply OPA policy in CI
infracost breakdown --path . --format json --out-file infracost.json

# Install OPA
brew install opa

# Evaluate policy
opa eval   --data infracost-policy.rego   --input infracost.json   "data.infracost.deny"   --format pretty

# Fail CI if any deny rules triggered
VIOLATIONS=$(opa eval   --data infracost-policy.rego   --input infracost.json   "count(data.infracost.deny)"   --format raw)

if [ "$VIOLATIONS" -gt "0" ]; then
  echo "Cost policy violations found. See details above."
  exit 1
fi

Infracost Cloud (Team Features)

Infracost Cloud (paid tier) adds:

1. Central dashboard: All repos, all PRs, cost trends
2. Slack/Teams notifications: Alert team when cost spike > threshold  
3. FinOps policies: No-code policy rules (max instance type, max cost increase)
4. Guardrails: Auto-fail PRs that violate policies
5. Budget tracking: Per-project/team cost forecasting

Pricing:
  Open source CLI: Free (always)
  Team: $99/month for up to 25 engineers
  Business: $499/month (SSO, audit logs, SLA)

ROI calculation:
  If the team ships 2 PRs/month with unintended $500+ cost increases,
  and each takes 4 engineer-hours to remediate post-deployment:
    Cost of remediation: 2 Γ— 4 Γ— $100 = $800/month engineering time
    + wasted cloud spend until fixed: $1,000/month
    Total monthly waste: $1,800/month
  Infracost Team: $99/month
  Monthly ROI: $1,701 (1718% ROI)

Conclusion

Infracost brings cloud cost into the development workflow where it belongs β€” at code review time, not at invoice time. The GitHub Actions integration takes under an hour to set up and immediately adds cost visibility to every infrastructure PR. OPA policy enforcement makes cost guardrails automatic rather than manual review processes.

The highest-leverage use is setting a cost increase threshold that triggers a mandatory FinOps review. This one workflow change prevents the architectural decisions that create years of unnecessary cloud spend.

P

Priya Sharma

Full-Stack Developer and open-source contributor with a passion for performance and developer experience.

Ready to Transform Your Infrastructure?

Let's discuss how we can help you achieve similar results.