Back to Blog
    Cost Optimization

    Right-Sizing Your EC2 Instances: A Data-Driven Approach

    Kostiantyn DementievJuly 15, 20257 min read

    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 CPUMax CPURecommendationAction
    < 20%< 40%Downsize 1 to 2 levelsImmediate candidate
    20 to 40%< 60%Downsize 1 levelTest carefully
    40 to 70%< 85%Leave it aloneWell sized
    > 70%> 85%Consider upsizingPerformance 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.