When we onboard a new client, the first thing we do is a cost audit. Not because we’re looking to impress them with a big number — but because it funds everything else. Find the waste, recover the budget, use that budget to do the work right.
It also sets the tone. A team that watches its first month with us end cheaper than the month before is a team that will let us touch the important things later. Nobody argues with a smaller bill.
Here’s the exact 30-minute sequence.
You need three things before the clock starts: read access to Billing and Cost Management, Cost Explorer enabled (it takes up to 24 hours to populate the first time, so switch it on the day before), and Compute Optimizer opted in for the account or the whole organisation. If any of these is missing, do that first and come back tomorrow. The audit is useless without data.
Step 1: Pull the Cost Explorer top-10 (5 min)
Open Cost Explorer, group by Service, sort by cost descending. Look at the top 10 line items. Anything surprising? An EC2 family you don’t recognise? An RDS instance that’s bigger than your biggest workload should need? Flag those for deeper inspection.
Set the range to the last three full months so a one-off doesn’t skew the picture, and use unblended costs so you see what actually hit the invoice. Then do one more pass grouped by Usage Type. Service-level grouping tells you that EC2 is 40% of the bill; usage-type grouping tells you that a chunk of that is DataTransfer-Regional-Bytes — cross-AZ traffic between services that could live in the same zone. Those are different problems with different fixes.
If the account is part of an organisation, group by Linked Account as well. The surprises are rarely in production. They’re in the sandbox account someone set up for a proof of concept eighteen months ago.
Write the flags down. You are not fixing anything yet — the whole point of the time limit is that you finish with a list, not a half-done change.
Step 2: Right-sizing report (10 min)
AWS Compute Optimizer is free and criminally underused. Run it, filter to “over-provisioned”, sort by estimated monthly savings. The average account we audit has £800–£2,000/month in right-sizing opportunities sitting in this report, untouched.
It covers EC2 instances, Auto Scaling groups, EBS volumes, Lambda functions and ECS on Fargate. By default it looks at 14 days of CloudWatch metrics; if you want a longer lookback you can pay for enhanced infrastructure metrics, which extends the window to around three months and is worth it for anything with a monthly or quarterly cycle.
Two caveats. First, Compute Optimizer cannot see memory unless the CloudWatch agent is installed and publishing it, so a recommendation that halves an instance’s RAM on a Java service deserves a second look. Second, “over-provisioned” is measured against observed load, not against what happens at month-end or during a marketing push. Check the peak, not the average, before you accept a downgrade.
What you want from this step is a shortlist of the five or six biggest savings where the risk is obviously low: a build agent, an internal tool, a staging database that mirrors production’s instance class for no reason anyone can remember. Those go straight into the next sprint.
Step 3: Idle resources (8 min)
Use Trusted Advisor (Business/Enterprise) or Cost Anomaly Detection to find:
- EC2 instances with CPU < 5% over 14 days
- RDS instances with zero connections
- Elastic IPs not attached to running instances (these cost money)
- NAT Gateways in regions with no traffic
If you don’t have a support tier that unlocks the full Trusted Advisor checks, the CLI gets you most of the way. Unassociated Elastic IPs, for example:
aws ec2 describe-addresses \
--query "Addresses[?AssociationId==null].PublicIp"
Note that since early 2024 AWS charges for every public IPv4 address, attached or not, so this list is a floor rather than the whole story. While you’re here, add three more sweeps that Trusted Advisor also surfaces: EBS volumes in the available state (detached from any instance and still billed), snapshots older than your retention policy, and load balancers with no healthy targets. Each one is small on its own. Together, on a mature account, they are rarely small.
NAT Gateways deserve a specific mention because they charge by the hour whether or not anything passes through them, and then again per gigabyte when it does. A “temporary” gateway in a region you no longer deploy to is one of the most common finds we make.
Step 4: Reserved Instance coverage (7 min)
Go to the RI Coverage report. Anything below 60% coverage on a stable workload is money left on the table. But — and this is critical — only buy RIs for workloads that have been stable for at least 90 days. The trap is locking in commitments on workloads that’re about to be re-architected.
Look at utilisation alongside coverage. Low coverage means you are paying on-demand for things you could commit to; low utilisation means you already committed to things you stopped running. The second is worse, because the money is already gone, and it is exactly what happens when someone buys reservations in the same week they start a migration.
For most teams today, a Compute Savings Plan is the better instrument than a classic RI: it applies across instance families, sizes and regions, so it survives the re-architecture that would have stranded an RI. One-year, no-upfront is the sensible default for a first commitment. Cover the base load you are certain about — the floor that is running at 3am on a Sunday — and leave the rest on demand until it has earned 90 days of stability.
Run this sequence monthly. Block 30 minutes on the last Friday of each month. It compounds.
What to do with the list
The audit produces a list, and a list nobody owns goes stale by the following Friday. So finish the half hour by doing three things.
- Rank every finding by monthly saving divided by effort. A stranded Elastic IP is a two-minute fix; a database downgrade needs a maintenance window. Do the quick ones today.
- Give each remaining item a name and a date. Cost work fails when it belongs to “the team”.
- Fix the cause, not just the instance. If you found an idle gateway, add a tagging rule or a budget alert so the next one gets caught in a week rather than a year.
The first audit on a new account is usually the biggest, because nobody has looked. The second and third are smaller. That is the point: after a few months the audit stops being a treasure hunt and becomes a routine that keeps the bill honest. The teams that skip it are not saving thirty minutes. They are paying the difference every month.


