Back to articles
5 min read

Predict your AWS bill with Infracost, stop the surprises

Know what your Terraform changes cost before you apply them. No more surprise $10k bills.

TerraformFinOpsDevOpsCost

You add one RDS instance in Terraform. Next month AWS charges you $847. You forgot to check the instance type

You switch from gp2 to gp3 storage to save money. Turns out you picked the wrong IOPS settings and now it costs more

A teammate deploys a NAT Gateway for testing. It stays up for 3 months. That’s $300 you didn’t need to spend

Infracost shows you what your changes cost before you apply them. Right in your terminal, right in your pull requests

Trying to understand your AWS bill

The AWS bill surprise nobody talks about

You know it’s coming. You make infrastructure changes, you wait for the bill, you hope it’s not too bad

I’ve seen teams spend 20 minutes in meetings discussing whether to add a load balancer. Nobody knows what it costs. Someone guesses ‘$50 a month?’ It’s actually $200

The classic move: spin up resources for a demo, forget about them, discover them 6 months later when someone finally reads the Cost Explorer

FinOps as a discipline exists because cloud bills are impossible to predict. The solution isn’t hiring a FinOps team, it’s putting cost visibility where decisions happen: in the code review

What Infracost actually does

You write Terraform. Infracost reads it and tells you the cost

# Install
curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh

# Show cost of current plan
infracost breakdown --path .

Output looks like this:

Project: my-infrastructure

 Name                                     Monthly Qty  Unit   Monthly Cost

 aws_instance.web
 ├─ Instance usage (Linux/UNIX, on-demand, t3.large)  730  hours       $60.74
 └─ root_block_device
    └─ Storage (general purpose SSD, gp3)             50  GB            $4.00

 aws_lb.main
 ├─ Application load balancer                         730  hours       $16.43
 └─ Load balancer capacity units                                       $5.84

 OVERALL TOTAL                                                         $87.01

No guessing. No ‘let me check the pricing page.’ Just numbers

The real power: diff between current and proposed infrastructure

infracost diff --path . --compare-to main

Shows you exactly what your PR will add to the monthly bill. Caught a $400/month mistake because someone selected the wrong RDS instance class

In CI/CD where it belongs

Every Terraform PR gets an Infracost comment showing the cost impact

# .github/workflows/infracost.yml
name: Infracost
on: [pull_request]
jobs:
  infracost:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: infracost/actions/setup@v2
        with:
          api-key: ${{ secrets.INFRACOST_API_KEY }}
      - run: infracost breakdown --path . --format json --out-file /tmp/infracost.json
      - uses: infracost/actions/comment@v1
        with:
          path: /tmp/infracost.json

PR comments look like:

💰 Infracost estimate: monthly cost will increase by $245 📈

  + aws_rds_cluster.postgres
    +$215  db.r5.large instance
    +$30   500GB storage

  ~ aws_instance.api
    -$61   t3.medium -> t3.large
    +$61

Total: $2,847 -> $3,092 (+$245/mo)

The person reviewing the PR sees this. They ask ‘do we really need r5.large?’ Turns out r5.xlarge was a typo. Caught before merge

This is FinOps. Not spreadsheets and quarterly reviews. Cost visibility in the workflow where changes happen

Real setup for client projects

I add this to every client’s Terraform repo

First, get an API key from Infracost (free for open source, they have a free tier for private repos too)

Add it to GitHub secrets as INFRACOST_API_KEY

Create the workflow file. Make it run on PRs targeting main

The result: every infrastructure change includes cost impact. No surprises

One client was adding Elasticache clusters in every environment. Dev, staging, prod, and three different regional failovers. Infracost showed $1,200/month. We switched to Redis on EC2 for non-prod. Cut it to $400

What it catches that you miss

Wrong instance types: You type t3.2xlarge when you meant t3.large. Infracost shows +$800/month. You fix it before apply

Forgotten resources: That test database you created 3 months ago? Still there. Still costing $215/month. Infracost breakdown shows everything

NAT Gateway sprawl: Every VPC gets a NAT Gateway. That’s $32/month per AZ. Multi-AZ across 3 environments? $288/month for internet access you might not need

Storage you didn’t optimize: Using gp2 instead of gp3 for EBS. Infracost shows the difference. Switch and save 20%

Load balancers for single instances: You created an ALB for one container. That’s $16/month + LCU charges. Just use a target group or direct instance access for dev

Integrates with Terragrunt too

Works fine with Terragrunt. Run it in each module directory:

# root.hcl can't estimate, but individual modules work
cd dev/vpc
infracost breakdown --path .

cd ../database
infracost breakdown --path .

Or use infracost breakdown --config-file infracost.yml with a config:

version: 0.1
projects:
  - path: dev/vpc
  - path: dev/database
  - path: dev/app

Shows combined estimate across all modules

I have this in a Makefile: make cost runs Infracost on all environments and shows total

When it’s worth it

Any team running Terraform in production. If your monthly cloud bill is over $1,000, this pays for itself immediately

Especially valuable when:

  • Multiple people make infrastructure changes
  • You have junior engineers learning Terraform
  • You’ve been surprised by bills before
  • You want cost reviews built into your process

Not worth it if you’re running a single EC2 instance that never changes. The cost is obvious

The FinOps discipline nobody wants

FinOps is spreadsheets, tagging policies, quarterly cost reviews, and someone telling you to rightsize your instances 6 months after you created them

That’s terrible. Nobody wants another meeting about cloud costs

Real FinOps: show costs when and where decisions happen. In the PR, before merge, when you can still change it without redeploying

Infracost does this. It doesn’t replace cost monitoring, but it prevents the mistakes that make monitoring necessary

A $500 mistake caught in code review costs $0. The same mistake caught in next month’s bill costs $500 plus the time to fix it

Getting started

Install it:

# Linux
curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh

# macOS
brew install infracost

# Arch
yay -S infracost

Get an API key:

infracost auth login

Run it on your Terraform:

cd your-terraform-project
infracost breakdown --path .

See the numbers. Add it to CI. Stop guessing what things cost

I spent 6 months telling clients ‘we should probably check what this costs.’ Now Infracost shows them. They see the number, they make informed decisions, nobody gets surprised by the bill

Cost visibility should be automatic, not something you remember to check. This makes it automatic

Reality is often more nuanced. But me? Nuance bores me. I'd rather be clear.

Comments