DEV Community

Cover image for Read-only by design: how I put a dollar figure on AWS waste without guessing
kirkle
kirkle

Posted on

Read-only by design: how I put a dollar figure on AWS waste without guessing

If you have ever tried to build a tool to find wasted AWS spend, you learn quickly that the API calls are the easy part. DescribeVolumes, GetMetricData, a few paginated List calls, and you are done. The hard part is deciding when you are actually allowed to put a dollar sign next to a finding, because a wrong number is worse than no number. A tool that says you could save about $70 a month and turns out to be off by half teaches the reader to ignore it completely.

So I set a strict rule that drives everything downstream: a dollar figure is computed only from a per-unit AWS list price and a resource fact the API actually reported. When the data is not there, the finding carries no figure at all and explicitly says so.

The log-retention check is a clean example of this. You can see that a log group never expires, and that is genuinely worth knowing, but the cost depends entirely on how many bytes have accumulated. If the API does not report that storage volume, the card shows the finding with no dollar amount attached. It does not estimate, because there is nothing solid to estimate from.

The second core design decision is the permission model, which is why the whole system is read-only by architecture rather than just read-only in marketing promises. Spend tracking needs exactly one permission: ce:GetCostAndUsage. The two security and waste scans are separate, opt-in features running once per account. Each is built strictly out of Get, List, and Describe actions combined with an explicit deny on write and delete.

There is one action whose name looks like a write: iam:GenerateCredentialReport. I describe it the way AWS does. AWS classifies it as a write action, but all it does is ask IAM to compile its own status report, changing nothing in your environment. Claiming AWS classifies it as read-only would be false, so the text states the literal truth instead.


The Cost-Waste Scan: Thresholds and Math

To make waste detection useful for a solo dev, the logic has to avoid false positives on low-traffic or staging environments. Here is how the waste checks pick their thresholds:

  • The 14-Day Idle Window: For idle resources like unattached Elastic Block Store (EBS) volumes or idle Elastic IPs, a resource must show zero or negligible activity for a rolling 14-day window before it triggers a waste finding.
  • Under-Utilized EC2 & RDS Instances: The scan looks at peak CPU utilization over a multi-day period. If an instance sits under 1% CPU utilization or flatlines way below its provisioned tier, it flags the resource.
  • Deriving the Figures: Instead of hardcoding static guesses, monthly savings are derived by taking the exact instance type or storage class, looking up its standard hourly AWS list price, and multiplying it out to a 730-hour month. If AWS doesn't expose the utilization metrics for a specific custom metric, the system logs the configuration issue without appending a fake dollar amount.

You can inspect what these findings look like on mock data right now without creating an account over at nimbuswatch.com/demo.


The 14-Check Security Audit

The security scan is designed around configuration oversights that frequently bite solo devs who aren't IAM specialists. It looks for structural vulnerabilities rather than scanning application-level CVEs. Key checks include:

  1. Root Account Guard: Checking whether MFA is enabled on the root account.
  2. Exposed S3 Buckets: Identifying public block settings or overly permissive ACLs/bucket policies.
  3. Open Security Group Ports: Flagging security groups exposing sensitive ports (like SSH port 22 or database ports 3306/5432) to 0.0.0.0/0.
  4. IAM Access Keys: Spotting active access keys that haven't been rotated in over 90 days.
  5. CloudTrail Verification: Ensuring logging is active across regions.
  6. Unencrypted Resources: Catching EBS volumes or RDS instances missing encryption at rest.

Every single finding throughout both the security and waste audits names the exact problem and gives you the one specific fix. It doesn't run automated scripts to modify your infrastructure; execution is entirely in your hands.


How Repeat Findings Are Handled

If a security misconfiguration or an idle resource is flagged today, it won't spam your dashboard or notification feed as a brand-new alert tomorrow. The engine fingerprints active findings against the resource ID and state. If the state hasn't changed, it remains part of your current active overview without piling up duplicate entries in your feed.


Disclosure: I built NimbusWatch, which is what this article is about, and AI assistance was used to help draft the wording of this post. I reviewed and edited every technical claim in it.

Top comments (0)