AWS Right-Sizing Guide 2024: Reduce Cloud Costs 30-50% with EC2, RDS & Compute Optimizer

Master AWS right-sizing with this comprehensive 3000+ word guide featuring 8 real code examples. Learn CloudWatch metrics analysis, AWS Cost Explorer and Compute Optimizer automation, EC2/RDS optimization with boto3, Reserved Instances and Savings Plans ROI calculations, Graviton migration strategies, and Auto Scaling with Terraform.

Cloud infrastructure costs represent one of the largest line items in modern IT budgets, with organizations often spending 30-40% more than necessary due to overprovisioned resources. According to Gartner, through 2024, 60% of infrastructure and operations leaders will encounter public cloud cost overruns that negatively impact their on-premises budgets. AWS right-sizing—the systematic process of matching your cloud resource allocation to actual workload requirements—stands as one of the most impactful cost optimization strategies available to cloud architects, DevOps engineers, and FinOps practitioners.

This comprehensive 3000+ word guide provides actionable strategies, real-world implementation examples, and 8 production-ready code samples using AWS CLI, Python boto3, CloudFormation, and Terraform. Whether you're managing a startup's infrastructure or optimizing enterprise-scale deployments across hundreds of accounts, these proven techniques can deliver 30-50% cost reductions while maintaining or improving application performance.

What You'll Learn in This Guide:

  • How to analyze CloudWatch metrics for accurate right-sizing decisions
  • Using AWS Cost Explorer and Compute Optimizer programmatically
  • Automating EC2 and RDS right-sizing with Python boto3 scripts
  • Calculating ROI for Reserved Instances and Savings Plans
  • Implementing Auto Scaling with Terraform for dynamic optimization
  • Migrating to AWS Graviton processors for 20-40% additional savings
  • Building automated right-sizing workflows with Lambda and EventBridge
  • Integrating with Warqline for continuous cost analytics

Understanding Right-Sizing Fundamentals: Key Metrics and Principles

Right-sizing is not a one-time activity but a continuous optimization discipline that requires understanding workload patterns, analyzing utilization metrics, and making data-driven decisions about resource allocation. Before diving into implementation, it's essential to understand the key metrics and principles that drive effective right-sizing.

What Is Right-Sizing and Why Does It Matter?

Right-sizing is the process of analyzing your cloud resources to ensure they match the actual requirements of your workloads. This involves:

  1. Downsizing: Reducing resource allocation for underutilized instances
  2. Upsizing: Increasing resources for performance-constrained workloads
  3. Instance family changes: Moving to more cost-effective instance types (e.g., T3 to T3a, M5 to M6g)
  4. Architecture optimization: Replacing always-on instances with serverless, spot, or scheduled capacity

The financial impact is substantial. Consider these real-world scenarios:

Scenario Before After Monthly Savings
Web servers at 15% CPU 10x m5.xlarge ($1,401/mo) 10x t3.medium ($302/mo) $1,099 (78%)
Database at 20% utilization db.r5.2xlarge ($876/mo) db.r5.large ($219/mo) $657 (75%)
Graviton migration 20x m5.large ($1,401/mo) 20x m6g.large ($1,121/mo) $280 (20%)

The Cost of Over-Provisioning

Many organizations provision resources based on peak capacity estimates or vendor recommendations that include significant headroom. While this approach ensures performance during demand spikes, it often results in resources running at 10-20% utilization during normal operations.

Consider a typical scenario: A team provisions m5.xlarge instances (4 vCPUs, 16 GB RAM) for an application that typically uses only 1.5 vCPUs and 6 GB RAM. This represents approximately 60% waste—resources you're paying for but not using. Multiply this across hundreds of instances, and the annual waste can reach hundreds of thousands of dollars.

Key Metrics for Right-Sizing Analysis

Effective right-sizing requires analyzing multiple dimensions of resource utilization. Each metric tells a different part of the story:

CPU Utilization Patterns: The most commonly analyzed metric, but often misunderstood. Look beyond average utilization to understand:

  • Percentile distributions (p50, p95, p99) to catch spikes
  • Time-based patterns (business hours vs. overnight, weekday vs. weekend)
  • Burst requirements for burstable instance type selection

Memory Utilization: Critical but often overlooked because it requires the CloudWatch Agent. Many applications are memory-bound rather than CPU-bound, making this metric essential for accurate right-sizing. Without memory metrics, you risk downsizing to instances that cause OOM (Out of Memory) errors.

Network I/O Characteristics: Network bandwidth requirements vary significantly across instance types. Understanding your application's network patterns helps avoid performance issues after right-sizing.

Disk Performance Metrics: IOPS and throughput patterns inform both instance type selection (some instances have better disk I/O) and EBS volume optimization.

Application-Level Metrics: Response times, queue depths, error rates, and application-specific metrics provide context that infrastructure metrics alone cannot offer.


AWS Cost Explorer Right-Sizing Recommendations: Complete Walkthrough

AWS Cost Explorer provides built-in right-sizing recommendations based on 14 days of CloudWatch metrics data. These recommendations analyze your EC2 instance usage and suggest modifications that could reduce costs while maintaining performance.

Understanding Cost Explorer Recommendation Types

AWS Cost Explorer provides three types of right-sizing recommendations:

  1. Modify Recommendations: Suggest changing to a smaller or different instance type while keeping the instance running
  2. Terminate Recommendations: Identify instances with very low utilization that could potentially be terminated
  3. Idle Resource Detection: Flags resources with near-zero utilization indicating potential orphaned resources

Accessing Right-Sizing Recommendations via AWS CLI

The AWS CLI provides programmatic access to right-sizing recommendations, enabling automation and integration with your cost management workflows:

#!/bin/bash
# Comprehensive EC2 right-sizing recommendations script

# Set variables
REGION="us-east-1"
OUTPUT_DIR="./rightsizing-reports"
mkdir -p $OUTPUT_DIR

echo "=== AWS Right-Sizing Recommendations Report ==="
echo "Generated: $(date)"

# Get same-family recommendations (conservative)
echo -e "
[1/4] Fetching same-family recommendations..."
aws ce get-rightsizing-recommendation     --service EC2     --configuration '{
        "RecommendationTarget": "SAME_INSTANCE_FAMILY",
        "BenefitsConsidered": true
    }'     --region $REGION     --output json > "$OUTPUT_DIR/same_family_recommendations.json"

# Get cross-family recommendations (aggressive)
echo "[2/4] Fetching cross-family recommendations..."
aws ce get-rightsizing-recommendation     --service EC2     --configuration '{
        "RecommendationTarget": "CROSS_INSTANCE_FAMILY",
        "BenefitsConsidered": true
    }'     --region $REGION     --output json > "$OUTPUT_DIR/cross_family_recommendations.json"

# Parse and display top 10 recommendations by savings
echo -e "
[3/4] Top 10 Right-Sizing Opportunities:"
jq -r '.RightsizingRecommendations | 
    sort_by(.ModifyRecommendationDetail.TargetInstances[0].EstimatedMonthlySavings | tonumber) | 
    reverse | 
    .[:10] | 
    .[] | 
    "Instance: (.CurrentInstance.ResourceId) | Current: (.CurrentInstance.InstanceType) | Recommended: (.ModifyRecommendationDetail.TargetInstances[0].InstanceType) | Savings: $(.ModifyRecommendationDetail.TargetInstances[0].EstimatedMonthlySavings)/month"'     "$OUTPUT_DIR/same_family_recommendations.json"

# Calculate total potential savings
echo -e "
[4/4] Calculating total savings potential..."
SAME_FAMILY_SAVINGS=$(jq '[.RightsizingRecommendations[].ModifyRecommendationDetail.TargetInstances[0].EstimatedMonthlySavings | tonumber] | add // 0' "$OUTPUT_DIR/same_family_recommendations.json")
CROSS_FAMILY_SAVINGS=$(jq '[.RightsizingRecommendations[].ModifyRecommendationDetail.TargetInstances[0].EstimatedMonthlySavings | tonumber] | add // 0' "$OUTPUT_DIR/cross_family_recommendations.json")

echo "=== Summary ==="
echo "Same-family monthly savings potential: \${SAME_FAMILY_SAVINGS}"
echo "Cross-family monthly savings potential: \${CROSS_FAMILY_SAVINGS}"
echo "Reports saved to: $OUTPUT_DIR/"

This script retrieves recommendations in two modes: SAME_INSTANCE_FAMILY (safer, keeps you within the same instance family) and CROSS_INSTANCE_FAMILY (more aggressive, may suggest different instance families like moving from M5 to T3 for burstable workloads).


AWS Compute Optimizer Integration: Advanced Right-Sizing Intelligence

While Cost Explorer provides basic right-sizing recommendations, AWS Compute Optimizer uses machine learning to analyze historical utilization metrics and provide more accurate, workload-specific recommendations. Compute Optimizer analyzes CPU, memory, network, and storage metrics to recommend optimal instance types.

Enabling and Using Compute Optimizer with boto3

Here's a comprehensive Python script to retrieve and analyze Compute Optimizer recommendations:

import boto3
from datetime import datetime
import json

def get_compute_optimizer_recommendations(region='us-east-1'):
    """
    Retrieve and analyze AWS Compute Optimizer recommendations
    for EC2 instances with detailed utilization metrics.
    """
    compute_optimizer = boto3.client('compute-optimizer', region_name=region)
    ec2 = boto3.client('ec2', region_name=region)
    
    recommendations = []
    
    try:
        response = compute_optimizer.get_ec2_instance_recommendations()
        
        for rec in response.get('instanceRecommendations', []):
            instance_arn = rec['instanceArn']
            instance_id = instance_arn.split('/')[-1]
            
            current_type = rec['currentInstanceType']
            finding = rec['finding']  # OVER_PROVISIONED, UNDER_PROVISIONED, OPTIMIZED
            
            instance_name = 'Unnamed'
            try:
                instance_details = ec2.describe_instances(InstanceIds=[instance_id])
                for tag in instance_details['Reservations'][0]['Instances'][0].get('Tags', []):
                    if tag['Key'] == 'Name':
                        instance_name = tag['Value']
                        break
            except:
                pass
            
            options = []
            for option in rec.get('recommendationOptions', []):
                projected_metrics = option.get('projectedUtilizationMetrics', [])
                cpu_projected = next(
                    (m['value'] for m in projected_metrics if m['name'] == 'CPU'),
                    'N/A'
                )
                options.append({
                    'instance_type': option['instanceType'],
                    'rank': option['rank'],
                    'performance_risk': option.get('performanceRisk', 0),
                    'projected_cpu': cpu_projected
                })
            
            utilization_metrics = rec.get('utilizationMetrics', [])
            current_cpu = next(
                (m['value'] for m in utilization_metrics if m['name'] == 'CPU'), 0
            )
            
            recommendations.append({
                'instance_id': instance_id,
                'instance_name': instance_name,
                'current_type': current_type,
                'finding': finding,
                'current_cpu_utilization': current_cpu,
                'recommendation_options': options
            })
    
    except Exception as e:
        print(f"Error retrieving recommendations: {e}")
        return []
    
    return recommendations

def generate_report(recommendations):
    over_provisioned = [r for r in recommendations if r['finding'] == 'OVER_PROVISIONED']
    
    print("=" * 60)
    print("AWS COMPUTE OPTIMIZER RECOMMENDATIONS REPORT")
    print("=" * 60)
    print(f"Total instances analyzed: {len(recommendations)}")
    print(f"Over-provisioned: {len(over_provisioned)}")
    
    if over_provisioned:
        print("
OVER-PROVISIONED INSTANCES:")
        for rec in over_provisioned:
            print(f"
{rec['instance_name']} ({rec['instance_id']})")
            print(f"  Current: {rec['current_type']} | CPU: {rec['current_cpu_utilization']:.1f}%")
            if rec['recommendation_options']:
                best = rec['recommendation_options'][0]
                print(f"  Recommended: {best['instance_type']}")

if __name__ == "__main__":
    recs = get_compute_optimizer_recommendations()
    generate_report(recs)

CloudWatch Metrics Analysis: Deep Dive with Python boto3

While Cost Explorer and Compute Optimizer provide recommendations, deep analysis of CloudWatch metrics enables more accurate, customized right-sizing decisions:

import boto3
from datetime import datetime, timedelta
import statistics

def analyze_ec2_utilization(region='us-east-1', days=14):
    """
    Comprehensive EC2 instance utilization analysis for right-sizing.
    """
    ec2 = boto3.client('ec2', region_name=region)
    cloudwatch = boto3.client('cloudwatch', region_name=region)
    
    end_time = datetime.utcnow()
    start_time = end_time - timedelta(days=days)
    
    instances = ec2.describe_instances(
        Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]
    )
    
    results = []
    
    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            instance_id = instance['InstanceId']
            instance_type = instance['InstanceType']
            
            instance_name = next(
                (tag['Value'] for tag in instance.get('Tags', []) if tag['Key'] == 'Name'),
                'Unnamed'
            )
            
            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,
                Statistics=['Average', 'Maximum']
            )
            
            if cpu_response['Datapoints']:
                cpu_data = [d['Average'] for d in cpu_response['Datapoints']]
                cpu_max_data = [d['Maximum'] for d in cpu_response['Datapoints']]
                
                avg_cpu = statistics.mean(cpu_data)
                max_cpu = max(cpu_max_data)
                sorted_cpu = sorted(cpu_data)
                p95_cpu = sorted_cpu[int(len(sorted_cpu) * 0.95)]
            else:
                avg_cpu = max_cpu = p95_cpu = 0
            
            recommendation = generate_recommendation(instance_type, avg_cpu, max_cpu, p95_cpu)
            
            results.append({
                'instance_id': instance_id,
                'instance_name': instance_name,
                'instance_type': instance_type,
                'cpu_avg': round(avg_cpu, 2),
                'cpu_max': round(max_cpu, 2),
                'cpu_p95': round(p95_cpu, 2),
                'recommendation': recommendation
            })
    
    return results

def generate_recommendation(instance_type, avg_cpu, max_cpu, p95_cpu):
    size_order = ['nano', 'micro', 'small', 'medium', 'large', 'xlarge', '2xlarge', '4xlarge']
    
    current_size = None
    instance_family = None
    for size in size_order:
        if instance_type.endswith('.' + size):
            current_size = size
            instance_family = instance_type.replace('.' + size, '')
            break
    
    if not current_size:
        return {'action': 'REVIEW_MANUALLY', 'reason': 'Unknown format'}
    
    current_index = size_order.index(current_size)
    
    if p95_cpu < 25 and max_cpu < 50 and current_index >= 1:
        new_size = size_order[current_index - 1]
        return {
            'action': 'DOWNSIZE',
            'suggested_type': f"{instance_family}.{new_size}",
            'savings': '30-50%'
        }
    elif p95_cpu > 75 or max_cpu > 95:
        if current_index < len(size_order) - 1:
            new_size = size_order[current_index + 1]
            return {'action': 'UPSIZE', 'suggested_type': f"{instance_family}.{new_size}"}
    
    return {'action': 'OPTIMAL', 'suggested_type': None}

if __name__ == "__main__":
    results = analyze_ec2_utilization()
    for r in results:
        if r['recommendation']['action'] != 'OPTIMAL':
            print(f"{r['instance_name']}: {r['instance_type']} -> {r['recommendation']}")

RDS Instance Optimization Strategies

Database instances often represent significant cost optimization opportunities. RDS right-sizing requires careful analysis because database performance directly impacts application responsiveness.

RDS Right-Sizing Analysis Script

import boto3
from datetime import datetime, timedelta

def analyze_rds_rightsizing(region='us-east-1', days=14):
    """Analyze RDS instances for right-sizing opportunities."""
    rds = boto3.client('rds', region_name=region)
    cloudwatch = boto3.client('cloudwatch', region_name=region)
    
    end_time = datetime.utcnow()
    start_time = end_time - timedelta(days=days)
    
    instances = rds.describe_db_instances()['DBInstances']
    results = []
    
    for instance in instances:
        db_id = instance['DBInstanceIdentifier']
        instance_class = instance['DBInstanceClass']
        
        cpu_stats = cloudwatch.get_metric_statistics(
            Namespace='AWS/RDS',
            MetricName='CPUUtilization',
            Dimensions=[{'Name': 'DBInstanceIdentifier', 'Value': db_id}],
            StartTime=start_time, EndTime=end_time,
            Period=3600, Statistics=['Average', 'Maximum']
        )
        
        memory_stats = cloudwatch.get_metric_statistics(
            Namespace='AWS/RDS',
            MetricName='FreeableMemory',
            Dimensions=[{'Name': 'DBInstanceIdentifier', 'Value': db_id}],
            StartTime=start_time, EndTime=end_time,
            Period=3600, Statistics=['Average', 'Minimum']
        )
        
        cpu_avg = sum(d['Average'] for d in cpu_stats['Datapoints']) / len(cpu_stats['Datapoints']) if cpu_stats['Datapoints'] else 0
        cpu_max = max((d['Maximum'] for d in cpu_stats['Datapoints']), default=0)
        mem_avg_gb = sum(d['Average'] for d in memory_stats['Datapoints']) / len(memory_stats['Datapoints']) / (1024**3) if memory_stats['Datapoints'] else 0
        
        if cpu_avg < 15 and cpu_max < 40 and mem_avg_gb > 4:
            recommendation = {'action': 'DOWNSIZE', 'savings': '30-50%'}
        elif cpu_avg > 70 or cpu_max > 90 or mem_avg_gb < 1:
            recommendation = {'action': 'UPSIZE', 'reason': 'High utilization'}
        else:
            recommendation = {'action': 'OPTIMAL'}
        
        results.append({
            'db_id': db_id, 'instance_class': instance_class,
            'cpu_avg': round(cpu_avg, 2), 'cpu_max': round(cpu_max, 2),
            'memory_gb': round(mem_avg_gb, 2), 'recommendation': recommendation
        })
    
    return results

if __name__ == "__main__":
    for r in analyze_rds_rightsizing():
        print(f"RDS {r['db_id']}: CPU {r['cpu_avg']}% -> {r['recommendation']['action']}")

Reserved Instances and Savings Plans: ROI Calculations

Right-sizing becomes even more impactful when combined with commitment-based discounts. After optimizing your instance sizes, lock in savings with Reserved Instances (RIs) or Savings Plans.

Understanding Your Options

Commitment Type Discount Flexibility Best For
No Commitment (On-Demand) 0% Maximum Variable workloads
Savings Plans (Compute) 20-66% High Changing architectures
Savings Plans (EC2) 30-72% Medium Stable EC2 usage
Reserved Instances (Standard) 30-72% Low Predictable workloads
Reserved Instances (Convertible) 20-66% Medium Long-term flexibility

Calculating ROI: A Real-World Example

Let's walk through a practical ROI calculation for a right-sized fleet combined with Savings Plans:

Scenario: After right-sizing, your production environment runs 20 x m6g.large instances 24/7 for a web application with predictable traffic patterns.

On-Demand Pricing (us-east-1):

  • m6g.large On-Demand: $0.077/hour
  • Monthly On-Demand cost: 20 × $0.077 × 730 hours = $1,124.20/month
  • Annual On-Demand cost: $13,490.40

Compute Savings Plan (3-year, All Upfront):

  • Effective rate: $0.029/hour (62% discount)
  • Annual cost: 20 × $0.029 × 8,760 hours = $5,080.80
  • Annual savings: $13,490.40 - $5,080.80 = $8,409.60

Combined Right-Sizing + Commitment Savings: If you originally ran 20 x m5.xlarge instances (before right-sizing):

  • Original m5.xlarge On-Demand: $0.192/hour
  • Original annual cost: 20 × $0.192 × 8,760 = $33,638.40
  • After right-sizing + Savings Plan: $5,080.80
  • Total annual savings: $28,557.60 (85% reduction)

This example demonstrates the compounding effect of right-sizing first, then applying commitment-based discounts.

When to Choose Each Option

Choose Compute Savings Plans when:

  • You're evolving your architecture (containers, serverless)
  • You plan to migrate between instance families or regions
  • You want maximum flexibility with good discounts

Choose EC2 Savings Plans when:

  • Your EC2 usage is stable and predictable
  • You've already optimized and right-sized your fleet
  • You want the best possible discount rate

Choose Reserved Instances when:

  • You have specific instance type and region requirements
  • You need to match capacity reservations
  • You want to resell unused capacity on the RI Marketplace

The Right-Sizing Before Commitment Rule

Critical best practice: Always complete your right-sizing analysis before purchasing any commitment-based discounts. Purchasing a 3-year Reserved Instance for an oversized instance locks you into paying for resources you don't need for three years. Right-size first, monitor for 2-3 months to confirm stability, then commit.


Auto Scaling Configuration: Terraform Examples

Auto Scaling automatically adjusts capacity based on demand, ensuring you pay only for resources you need:

# Terraform configuration for cost-optimized Auto Scaling

resource "aws_launch_template" "app" {
  name_prefix   = "production-app-"
  image_id      = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.medium"
  
  monitoring {
    enabled = true
  }
  
  metadata_options {
    http_tokens   = "required"
    http_endpoint = "enabled"
  }
  
  block_device_mappings {
    device_name = "/dev/xvda"
    ebs {
      volume_size = 20
      volume_type = "gp3"
      encrypted   = true
    }
  }
}

resource "aws_autoscaling_group" "app" {
  name                = "production-app-asg"
  vpc_zone_identifier = var.private_subnet_ids
  min_size            = 2
  max_size            = 20
  desired_capacity    = 2
  
  mixed_instances_policy {
    instances_distribution {
      on_demand_base_capacity                  = 1
      on_demand_percentage_above_base_capacity = 25
      spot_allocation_strategy                 = "capacity-optimized"
    }
    
    launch_template {
      launch_template_specification {
        launch_template_id = aws_launch_template.app.id
        version            = "$Latest"
      }
      
      override {
        instance_type     = "t3.medium"
        weighted_capacity = "1"
      }
      override {
        instance_type     = "t3a.medium"
        weighted_capacity = "1"
      }
      override {
        instance_type     = "m6g.medium"
        weighted_capacity = "1"
      }
    }
  }
  
  warm_pool {
    pool_state = "Stopped"
    min_size   = 1
  }
}

resource "aws_autoscaling_policy" "cpu_tracking" {
  name                   = "cpu-tracking"
  autoscaling_group_name = aws_autoscaling_group.app.name
  policy_type            = "TargetTrackingScaling"
  
  target_tracking_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ASGAverageCPUUtilization"
    }
    target_value = 60.0
  }
}

resource "aws_autoscaling_schedule" "scale_up" {
  scheduled_action_name  = "scale-up-business-hours"
  autoscaling_group_name = aws_autoscaling_group.app.name
  min_size               = 4
  desired_capacity       = 6
  recurrence             = "0 8 * * MON-FRI"
  time_zone              = "America/New_York"
}

Graviton Migration: Achieve 20-40% Additional Savings

AWS Graviton processors (ARM-based) offer the best price-performance ratio for compatible workloads. Migrating from x86 to Graviton can deliver 20-40% cost savings:

Graviton Instance Comparison

x86 Instance Graviton Equivalent Price Difference
m5.large m6g.large -20%
r5.2xlarge r6g.2xlarge -20%
c5.4xlarge c6g.4xlarge -20%

CloudFormation Template for Graviton

AWSTemplateFormatVersion: '2010-09-09'
Description: Graviton-based Auto Scaling Group

Resources:
  GravitonLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: graviton-template
      LaunchTemplateData:
        ImageId: !Ref GravitonAMI
        InstanceType: m6g.large
        MetadataOptions:
          HttpTokens: required
        BlockDeviceMappings:
          - DeviceName: /dev/xvda
            Ebs:
              VolumeSize: 20
              VolumeType: gp3
              Encrypted: true

  GravitonASG:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref GravitonLaunchTemplate
        Version: !GetAtt GravitonLaunchTemplate.LatestVersionNumber
      MinSize: 2
      MaxSize: 10
      VPCZoneIdentifier: !Ref SubnetIds

  GravitonAMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64

Right-Sizing Workflow Automation with Lambda

Automate your right-sizing workflow to continuously identify opportunities:

import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    """Automated right-sizing workflow triggered by EventBridge."""
    ce = boto3.client('ce')
    sns = boto3.client('sns')
    
    SNS_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:rightsizing-alerts'
    
    response = ce.get_rightsizing_recommendation(
        Service='EC2',
        Configuration={
            'RecommendationTarget': 'SAME_INSTANCE_FAMILY',
            'BenefitsConsidered': True
        }
    )
    
    recommendations = response.get('RightsizingRecommendations', [])
    
    if not recommendations:
        return {'statusCode': 200, 'body': 'No recommendations'}
    
    total_savings = sum(
        float(r.get('ModifyRecommendationDetail', {})
              .get('TargetInstances', [{}])[0]
              .get('EstimatedMonthlySavings', '0'))
        for r in recommendations
    )
    
    message = f"""
AWS Right-Sizing Report - {datetime.now().strftime('%Y-%m-%d')}
Total Recommendations: {len(recommendations)}
Estimated Monthly Savings: USD {total_savings:,.2f}
Estimated Annual Savings: USD {total_savings * 12:,.2f}
"""
    
    sns.publish(
        TopicArn=SNS_TOPIC_ARN,
        Subject=f'Right-Sizing: USD {total_savings:,.0f}/month savings available',
        Message=message
    )
    
    return {'statusCode': 200, 'body': json.dumps({'savings': total_savings})}

Working with Warqline

We are a cloud engineering consultancy and an official AWS and Google Cloud partner. If you are running this in production and want a second pair of eyes, we scope work in a free 45-minute technical call: you describe what you are running and what worries you, and we tell you what we would look at first.

Talk to an engineer

Conclusion: Building a Continuous Optimization Culture

Right-sizing is not a one-time project but an ongoing discipline. The most successful programs share these characteristics:

Regular Review Cadence: Establish monthly or quarterly reviews as workload patterns change.

Automated Monitoring: Use tools like Warqline to continuously surface opportunities.

Cross-Functional Ownership: Collaboration between finance, engineering, and operations teams.

Start Conservative: Capture 80% of savings safely rather than risking outages.

Key Takeaways

  1. Right-sizing delivers 30-50% cost savings when implemented systematically
  2. Combine with Savings Plans/RIs for maximum impact
  3. Migrate to Graviton for an additional 20-40% savings
  4. Automate analysis using Compute Optimizer, boto3 scripts, and Warqline
  5. Implement Auto Scaling to match capacity with demand
  6. Review continuously as workload patterns evolve

Ready to accelerate your cost optimization journey? Connect your AWS account to Warqline and start receiving actionable recommendations within minutes.