Most cost reviews we are asked to do start with the same sentence: "we are thinking about Savings Plans". It is a reasonable instinct. It is also the last step, not the first. A commitment discounts the capacity you run; if a third of that capacity is waste, you have just signed a one-year contract to keep paying for it at a discount.
The order below is what we follow in the ten-day assessment that opens every cloud cost optimisation project. Every step is read-only, and every number comes from Cost Explorer or the Cost and Usage Report (CUR), never from a guess.
1. Allocation: who owns each euro
Before touching anything, tag coverage. Group the last three months by the Environment and Owner cost allocation tags and look at how much lands in "no tag". In accounts that have never done this, it is usually between 30 and 60 percent.
You cannot optimise what nobody owns. Fixing this is cheap: a tagging policy in AWS Organizations, an SCP that refuses untagged RunInstances, and one week to backfill the existing resources with a script. Everything that follows becomes measurable per team.
2. Idle and orphaned resources
This is where the fastest money is, and it needs no architecture discussion.
- EBS volumes in
availablestate, and snapshots of volumes that no longer exist. - Elastic IPs not attached to anything. They are cheap individually and silly in aggregate.
- Load balancers with zero healthy targets for the last two weeks.
- RDS instances with less than five connections a day, usually a test database someone forgot.
- NAT gateways in subnets where nothing runs any more. Each one is a fixed monthly cost plus data processing.
A terraform state list compared with the live inventory usually explains how these appeared (this is one of the views Skyline builds for you): someone destroyed a stack by hand and left the pieces Terraform did not know about.
3. Rightsizing with real metrics
Compute Optimizer is free and most accounts have never opened it. It looks at fourteen days of CloudWatch metrics and proposes a smaller instance type where CPU and memory allow it. Two rules we apply on top:
- Trust the recommendation only when the memory agent is installed. Without it, Compute Optimizer guesses memory, and it guesses optimistically.
- Move generations before moving sizes. An
m5.xlargetom7g.xlargechange keeps the size, cuts the price and usually improves p99, but it requires an ARM build of your image. Check that first.
Databases deserve a separate pass: db.r5.2xlarge instances running at eight percent CPU are a classic, because someone sized them for a migration weekend two years ago.
4. Data transfer and storage classes
Data transfer is the line nobody understands and everybody pays. Three checks:
- Cross-AZ traffic between services that could sit in the same zone. Kubernetes clusters with topology-unaware scheduling are the usual source.
- NAT gateway data processing for traffic to S3 or DynamoDB. A gateway VPC endpoint makes it free.
- S3 storage classes. Buckets with years of logs in Standard. A lifecycle rule to Intelligent-Tiering or Glacier Instant Retrieval is a one-line change that pays every month.
5. Now, and only now, commitments
With the waste gone, the remaining baseline is what you actually need. Buy against that.
- Start with a Compute Savings Plan at a coverage of around 60 to 70 percent of the baseline. It is the most flexible and survives instance family changes.
- Add Reserved Instances for RDS and ElastiCache, which Savings Plans do not cover.
- Re-evaluate quarterly. Commitments are not a one-off decision.
The usual result of the five steps is between 25 and 40 percent off the monthly bill, with roughly half of that coming from layers two to four, before any commitment is signed.
What to do this week
Open Cost Explorer, group by usage type, and look at the top ten lines for the last month. If you cannot name the owner of each one, start with step one. If you can, start with step two. Either way, do not buy the Savings Plan yet.