The bill on this account had roughly doubled over a year while the team swore nothing had changed. I pointed four open-source FinOps tools at it, one after another, to see which of them could explain why. Each one was useful. None of them was the answer, and the gaps were more interesting than the findings.
I am deliberately not going to give you a table of dollar figures. The numbers were specific to one account and would be misleading anywhere else. What transfers is the shape of what each tool sees, and, more importantly, the shape of what it does not.
Cost tooling does not fail by being wrong. It fails by being confidently incomplete.
Infracost: what it would cost, not what it does cost
Infracost reads Terraform and tells you the monthly price of what you are about to apply. It runs in CI, comments on the pull request, and it is genuinely the best guardrail I know for stopping an expensive change before it lands.
infracost breakdown --path ./infra --format table
What it found: two environments where the instance class had been bumped "temporarily" in a PR nobody had reverted. Infracost had flagged the increase at the time. The comment had been read and approved.
What it missed: everything that was not in Terraform. Around a third of this account had been created by hand in the console or by a script that had long since been deleted. Infracost has no opinion on those resources because it never sees them. It also prices what you declared, not what you use: an on-demand instance running at four percent CPU costs exactly the same on its report as one running flat out.
Komiser: the inventory you did not know you needed
Komiser connects to the account, walks every region and service it supports, and builds an inventory with a cost attached to each item. You get a dashboard, filters, tags, and the ability to answer "what do we actually have?" without opening twelve consoles.
What it found: the click-ops third that Infracost could not see. Load balancers with no targets. Elastic IPs attached to nothing. A NAT gateway in a region the team did not know they used. A cluster of snapshots from a migration that finished eighteen months ago. Just seeing the list was worth the setup.
What it missed: the "why". Komiser could tell me a resource existed and roughly what it cost, but not whether it was needed, not who owned it, and not whether the size was right. Inventory is the start of a conversation with the team, not a decision. Coverage also stops at the services it has integrations for, so a few of the more obscure line items on the bill never appeared.
Cloud Custodian: rules, but only the rules you wrote
Cloud Custodian is a policy engine. You describe a condition in YAML, it finds every resource matching that condition, and optionally acts on it: tag it, stop it, notify someone, delete it after a grace period. It is the tool I would pick if I could only keep one, because it turns a finding into a habit.
policies:
- name: ebs-unattached-older-than-30-days
resource: aws.ebs
filters:
- Attachments: []
- type: value
key: CreateTime
value_type: age
op: greater-than
value: 30
actions:
- type: tag
key: custodian_status
value: unattached-30d
What it found: exactly what I asked for. Unattached volumes, stopped instances still holding storage, old snapshots, untagged resources. Once the policies existed, they ran every night and the list stopped growing.
What it missed: everything I had not thought to write a policy for. Custodian has no built-in notion of waste; it has filters. If you do not know that idle NAT gateways are a common leak, you will not write the rule, and Custodian will not tell you. It is also blind to pricing. It can find the oversized instance but cannot tell you what right-sizing it would save.
OpenCost: precise inside Kubernetes, silent outside it
OpenCost runs inside a cluster and allocates the cost of nodes down to namespaces, deployments and pods, using real usage rather than requests. If you run Kubernetes, it answers the question every platform team gets asked: which team is spending the money?
What it found: one namespace consuming most of the cluster's cost through a handful of pods whose resource requests were several times what they actually used. The nodes were sized for the requests. Nobody had looked in a year.
What it missed: the other seventy percent of the bill. OpenCost is Kubernetes-shaped by design. Managed databases, object storage, data transfer, the NAT gateways, the load balancers: none of it exists as far as OpenCost is concerned. It also relies on you having proper labels, and this cluster did not, so a meaningful slice of cost landed in the bucket called "unallocated", which is a polite name for "nobody".
What all four missed together
This is the part I actually wanted to learn. If you run all four, you get a decent inventory, a nightly cleanup, cost-aware pull requests and per-team allocation in the cluster. That is a lot. And yet the same handful of things fell through every tool.
- Data transfer. Cross-AZ and cross-region traffic and NAT egress were among the fastest-growing lines on this bill. No tool attributed them to the architecture decision that caused them.
- Commitments. None of the tools could tell me how much of the on-demand spend was covered by Savings Plans or reservations, or what a sensible commitment would look like. The biggest single saving available was invisible to all four.
- Ownership. Every tool could list a resource. None could say whose it was, because that knowledge lived in people, not tags.
- Trend. Each tool shows you today. The original question was "why did this double over a year?", and answering it meant pulling Cost Explorer exports and doing the comparison by hand.
- The account next door. Everything above was one account. Most organisations have dozens, and the interesting waste is often the duplicate running in a sibling account nobody compared against.
What I would tell a team starting today
Use the free tools. They are good, and they will pay for the afternoon it takes to set them up many times over. Start with an inventory so you know what exists, add Custodian policies so the obvious waste stops accumulating, and put Infracost in CI so the next expensive change gets a comment before it merges.
Then be clear-eyed about the gap. The open-source layer finds waste. It does not find the reason, it does not see the commitments, it does not remember last quarter, and it does not know who to ask. That gap is where the money you are actually looking for tends to sit, and closing it needs either a person with time and context or a system built to hold both. On this account it was a person, for a while. It usually is, until it is not.