Right-Sizing Your EC2 Instances: A Data-Driven Approach
The problem: instance sizes get chosen once, under time pressure, with no data. Then they never get revisited. Oversized instances are the most common finding in an AWS audit, and the cheapest one to fix.
Right-sizing means matching instance type and size to what the workload measurably needs. It is usually the fastest reduction available on an AWS bill, because it takes no application changes and no commitment. It is also the one most likely to cause an incident if you skip the measurement step.
The methodology
Phase 1: data collection (2 to 4 weeks)
Collect CPU, memory, network, and storage utilization across both peak and quiet periods. Two weeks is the minimum that captures a full business cycle including month-end.
Phase 2: analysis and recommendations
Combine AWS Compute Optimizer output with your own queries. Sort candidates by monthly saving so you know which ten instances are worth the risk of touching.
Phase 3: testing and validation
Apply each recommendation in a non-production environment carrying comparable load before it goes anywhere near production.
Phase 4: rollout and monitoring
Resize inside a maintenance window, in batches, and watch latency and error rates for 72 hours before starting the next batch.
Using AWS Compute Optimizer
Compute Optimizer analyzes your historical utilization and returns sizing recommendations per instance. It is free, and it is the right starting point. Note that it reads memory utilization only if the CloudWatch agent is installed, so without the agent every recommendation is CPU-only.
Enable Compute Optimizer
aws compute-optimizer get-enrollment-status aws compute-optimizer update-enrollment-status --status Active # Get recommendations aws compute-optimizer get-ec2-instance-recommendations \ --instance-arns arn:aws:ec2:us-east-1:123456789012:instance/i-1234567890abcdef0
Custom analysis script
When you want the raw numbers rather than a recommendation, pull them from CloudWatch directly:
import boto3
from datetime import datetime, timedelta
def analyze_instance_utilization(instance_id, days=30):
cloudwatch = boto3.client('cloudwatch')
ec2 = boto3.client('ec2')
end_time = datetime.utcnow()
start_time = end_time - timedelta(days=days)
# Get CPU utilization
cpu_response = cloudwatch.get_metric_statistics(
Namespace='AWS/EC2',
MetricName='CPUUtilization',
Dimensions=[{'Name': 'InstanceId', 'Value': instance_id}],
StartTime=start_time,
EndTime=end_time,
Period=3600, # 1 hour periods
Statistics=['Average', 'Maximum']
)
# Calculate averages
cpu_avg = sum(d['Average'] for d in cpu_response['Datapoints']) / len(cpu_response['Datapoints'])
cpu_max = max(d['Maximum'] for d in cpu_response['Datapoints'])
# Get instance details
instance = ec2.describe_instances(InstanceIds=[instance_id])
instance_type = instance['Reservations'][0]['Instances'][0]['InstanceType']
return {
'instance_id': instance_id,
'instance_type': instance_type,
'cpu_average': cpu_avg,
'cpu_maximum': cpu_max,
'recommendation': get_recommendation(cpu_avg, cpu_max, instance_type)
}Decision matrix
A starting heuristic for CPU-bound workloads. Memory-bound services need their own thresholds.
| Average CPU | Max CPU | Recommendation | Action |
|---|---|---|---|
| < 20% | < 40% | Downsize 1 to 2 levels | Immediate candidate |
| 20 to 40% | < 60% | Downsize 1 level | Test carefully |
| 40 to 70% | < 85% | Leave it alone | Well sized |
| > 70% | > 85% | Consider upsizing | Performance risk |
Implementation practices
Before you resize anything
- Test in non-production first, under comparable load
- Treat memory-bound applications as a separate exercise
- Check for seasonal traffic you have not seen yet in the window
- Watch latency and errors, not just CPU, for 72 hours after the change
- Know the rollback command before you run the change
Automated right-sizing
For workloads with a predictable daily shape, a scheduled Lambda can resize on a calendar rather than a threshold. Reserve fully automatic reactive resizing for stateless tiers, where a bad decision costs a restart and nothing more.
If you want a second pair of eyes on your fleet, our AWS cost audit includes right-sizing analysis, at a fixed price.
From a real engagement
On a martech SaaS (NDA), right-sizing plus commitment coverage took 45% off the monthly AWS bill. Right-sizing was the first phase and it needed no application changes, which is why it went first.