AkolagTech
2026-07-20 AkolagTech 5 min read

Cloud audit: the 6 things quietly costing you money

Six specific, common AWS cost-optimization gaps we look for in a cloud audit — what they are, why they happen, and how to fix each one.

cloud cost optimizationAWScloud auditFinOps

Most cloud waste isn’t dramatic. It’s not one giant misconfigured cluster — it’s a handful of small, boring leaks that accumulate month after month because nobody’s job is to notice them. A cloud cost audit exists to find exactly this kind of waste: not glamorous, just persistent.

Here are six of the most common patterns we look for, in roughly the order they tend to show up.

1. Orphaned EBS volumes

When you terminate an EC2 instance, its attached storage (EBS volumes) doesn’t always go with it. Unless “delete on termination” was explicitly set, the volume survives the instance — detached, doing nothing, and billed by the gigabyte-month for as long as it exists. This is especially common in dev/test environments where instances get spun up and torn down frequently, and in teams that scaled infrastructure quickly without standardizing termination settings.

The fix: periodically list volumes with no attached instance, confirm none are needed for recovery, and delete them. Going forward, set “delete on termination” as the default for any non-critical volume, and snapshot anything you might actually need before it’s ever detached.

2. Over-provisioned instances

It’s common to size a server for peak load and then never revisit that decision. A database instance sized for a traffic spike that happens twice a year runs at that size the other 363 days too, and you pay for capacity you’re not using nearly all the time. This tends to happen because right-sizing requires someone to actually look at utilization data on a recurring basis — and once an instance is “working,” there’s rarely a trigger to revisit its size.

The fix: pull CPU, memory, and network utilization from CloudWatch over a meaningful window (at least a couple of weeks, ideally including your peak period) and compare it against what you’re paying for. Downsizing an instance that consistently runs under 20-30% utilization is usually a safe, low-risk change with no user-facing impact.

3. Cross-AZ data transfer

Traffic that stays inside a single Availability Zone is typically free or very cheap. The same traffic moving between Availability Zones within the same region is billed, in both directions, and it’s one of the least visible line items on a bill because it doesn’t show up as a named resource — it shows up as a data transfer charge that’s easy to overlook. This adds up fast in chatty multi-tier architectures where a web tier in one AZ is constantly calling a database or cache in another.

The fix: look at whether your application, database, and cache tiers are spread across AZs in a way that generates constant cross-AZ chatter for no redundancy benefit. Sometimes cross-AZ traffic is the right tradeoff for availability — the point isn’t to eliminate it, it’s to make sure you’re paying for it on purpose, not by accident of how things happened to get deployed.

4. Unused Elastic IPs

Public IPv4 addresses are billed by AWS whether or not they’re actively in use — this has been true across the board since AWS changed its public IPv4 pricing model in 2024. An Elastic IP reserved for a project that got cancelled, or left behind after an instance was replaced, is pure waste: it provides no benefit and costs money every hour it exists.

The fix: audit allocated Elastic IPs against what’s actually in use, and release anything that isn’t tied to a live, needed resource. This is one of the fastest audit findings to fix — there’s essentially never a reason to keep an EIP that isn’t attached to something running.

5. No S3 lifecycle policies

Object storage is cheap per gigabyte, which is exactly why it’s easy to ignore — until you’re storing terabytes of logs, backups, or old uploads at the default “Standard” storage tier indefinitely, when most of that data is rarely, if ever, read again after the first few weeks. Standard storage is priced for frequent access; a lot of what sits in it doesn’t need frequent access at all.

The fix: set lifecycle rules that automatically transition objects to a cheaper storage class (Infrequent Access, then Glacier or Deep Archive) after a defined age, and expire objects outright if you have data with a genuine retention limit. This is a one-time configuration that keeps paying off automatically, with no ongoing manual work.

6. Idle RDS instances

Non-production databases — staging, QA, a developer’s personal sandbox — often run 24/7 on the same instance class as production, even though nobody touches them outside business hours. A database that’s only actively used 40 hours a week is still being billed for all 168.

The fix: for non-production databases, either schedule automatic stop/start (stopped outside working hours, started each morning) or move to a serverless/on-demand database option that scales down to near-zero when idle. Production databases are a different conversation — right-sizing and reserved-capacity pricing usually matter more there than scheduling.

The pattern behind all six

None of these are exotic. They’re the result of infrastructure that was provisioned correctly at one point in time and never revisited as usage changed — which is normal, because reviewing cloud spend isn’t anyone’s full-time job at most SMBs and mid-market companies. That’s exactly the gap a periodic cloud audit is meant to close: not a one-time cleanup, but a recurring check that catches this kind of drift before it becomes a permanent line item on the bill.

If you want a straight answer on whether these patterns exist in your own AWS account — and roughly what fixing them would be worth — that’s what our cloud cost optimization engagement is for. We look at your actual account, not a generic checklist, and we tell you plainly if we don’t find much to fix.

Want help applying this to your business?

Book an assessment ↗