Design Review: Know the Cost Before You Merge

Most infrastructure changes are reviewed for correctness and never for cost. Design Review prices a Terraform plan against what your resources really cost today, in the app or as a comment on every pull request.

A pull request adds a node group and moves the API servers up a size. Two reviewers check the Terraform. Both approve. Nobody asks what it costs.

That is not carelessness. The plan output says ~ instance_type = "m5.large" -> "m5.xlarge", not "about $400 a month more". Working out the money means opening a pricing page, finding the region, multiplying by hours, and remembering whether this account has a savings plan. So the cost conversation happens a month later, when the bill arrives and someone asks why it went up.

List price is the wrong starting point

The usual fix is to price the plan at list price. It is better than nothing, and for brand new resources it is the best you can do.

For anything that already runs, it is often wrong. Your bill carries reservations, savings plans, negotiated discounts, licenses that come with the VM, and real usage. Say a VM bills you $52 a month because a reservation covers most of it. Resize it to the next size up, and list price says it goes from $70 to $140, so +$70 a month. If your current discount carries over to the new size, the increase is closer to $52. The difference matters, and so does knowing which assumption sits behind the number. The reviewer usually sees neither.

What Design Review does

Design Review starts from what each resource really costs you today, then prices the change on top.

  1. Run terraform plan and terraform show -json as usual.
  2. Upload or paste the JSON, or let your pipeline send it.
  3. Each change gets a row: what runs now, what runs after apply, and the change per month.

A resource that already runs uses its billed spend as the "before". When it is resized, that real figure is scaled by how much the list price changes. This assumes your current discount carries over to the new size. It may not: a reservation might not cover the new size, or a savings plan might already be used up elsewhere. Scaled figures are marked so you know which numbers rest on that assumption. A new resource uses list price for its region. Kubernetes node pools use what the CostOptix agent sees on the cluster.

Today it prices compute:

Cloud Priced
AWS EC2 instances, Auto Scaling groups (from their launch template), EKS node groups
Azure Virtual machines, scale sets, AKS node pools
Google Cloud Compute Engine instances, managed instance groups, GKE node pools

Everything else in the plan, such as storage, databases and load balancers, is listed as not priced. It is never guessed. The summary says how many changes were priced out of how many changed, so nobody mistakes a partial total for the whole picture.

No plan yet? Start with the system

Plans price a change someone has already written. Often the question comes earlier: what does this product cost to run, and what happens if we change it?

A system in Design Review groups the cloud accounts, tags, Kubernetes namespaces and hosts a product runs on, and shows what it really costs each month. Scenarios then price changes to it before anyone writes Terraform:

  • resize a VM from your imported Terraform state, or move it to another region
  • change a node pool's size or node count
  • change a workload's replicas or its CPU and memory requests
  • remove a resource you are billed for

Each scenario starts with what the system costs today and estimates the change under the proposed configuration. Compare alternatives side by side before anyone writes Terraform, then record the option you choose and why.

On every pull request

A cost check only helps if it shows up where the decision is made. Design Review runs in CI, so the estimate lands on the pull request as a comment:

+$376.53 per month ($407.54 now, $784.07 after apply)

Change Resource Now After Per month
Add aws_eks_node_group.workers - 3 x m5.large, $210.24 +$210.24
Remove google_compute_instance.legacy_batch n2-standard-4, $141.79 - -$141.79
Add azurerm_linux_virtual_machine.reporting - Standard_D4s_v5, $140.16 +$140.16
Change google_container_node_pool.shop 2 x e2-standard-4, $195.67 3 x e2-standard-4, $293.51 +$97.84
Change aws_instance.api m5.large, $70.08 m5.xlarge, $140.16 +$70.08

5 of 6 changes priced. Not priced: aws_s3_bucket (1).

Setup is a copy-paste step for GitHub Actions, GitLab CI or Azure Pipelines:

  • A narrow key. The key you create can post plans for pricing and nothing else. It cannot read your cost data.
  • Only what pricing needs leaves the pipeline. A small jq filter strips the plan down to resource changes and provider regions before it is sent. The plan itself is never stored.
  • One comment per pull request. Each push updates the same comment, so the thread doesn't fill up with estimates.
  • Your pipeline posts it. CostOptix holds no credentials to your Git provider. The response carries the comment as Markdown, and your step posts it.
  • An optional threshold. Fail the step when a change adds more than, say, $500 a month or 20% to what those resources cost today. Set either limit or both. It is off unless you turn it on.

Each pull request also keeps one review in CostOptix, with the repository, pull request and commit on it, so the full breakdown is one click from the comment.

Then check what it really cost

An estimate is a prediction. On a saved review or scenario, We're doing this records the decision with the expected change and a reason. Mark it rolled out when it ships. Once the first full month after rollout settles, CostOptix compares it with the last full month before rollout, both scaled to the same 730-hour month the estimate uses. If the real change is within 15% of the estimate (or $5 for small changes), it landed on target. Otherwise it was over or under. Admins can set that tolerance anywhere from 5% to 50%.

It's a before and after comparison, not proof of cause. A plan checked resource by resource only looks at the resources it changed, but usage or price changes on those resources still count. A plan or scenario checked against its system can also be moved by other changes in that system.

That closes the loop most cost reviews never close. The question stops being "what will this cost?" and becomes "what did we say it would cost, and were we right?"

What it changes

Cost becomes part of the review, next to correctness and security, without anyone opening a pricing page. Reviewers see the number in the same place they see the diff. Small changes stay small. The big ones get a conversation before they merge, not after the invoice.

Read the setup guide, try it on your own plans or look around the demo.