Skip to main content

AWS Cost Optimisation

EC2 Cost Optimisation: Strategies for Reducing Compute Spend

Practical strategies for optimising EC2 costs including right-sizing, Spot instances, Savings Plans, and automation techniques for Australian businesses.

CloudPoint

CloudPoint Team

EC2 is often the largest line item on AWS bills. For Australian businesses running compute-intensive workloads, optimising EC2 costs can yield significant savings without sacrificing performance or reliability.

Understanding EC2 Pricing

EC2 costs come from:

  • Instance hours: Charged per second (60-second minimum)
  • Instance type: CPU, memory, storage, network performance
  • Region: Sydney (ap-southeast-2) generally 10-15% more than US regions
  • Operating system: Windows typically 30-40% more than Linux
  • Tenancy: Dedicated instances cost significantly more

Example Pricing (Sydney region, Linux):

  • t3.medium: $0.0544/hour ($40/month)
  • m6i.large: $0.125/hour ($91/month)
  • c6i.xlarge: $0.221/hour ($161/month)

Running 24/7 adds up quickly.

Strategy 1: Right-Sizing

Assess Current Utilization

Use CloudWatch metrics to identify oversized instances:

aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
  --start-time 2025-10-01T00:00:00Z \
  --end-time 2025-11-01T00:00:00Z \
  --period 3600 \
  --statistics Average,Maximum \
  --region ap-southeast-2

Red flags:

  • Average CPU < 20%
  • Maximum CPU < 40%
  • Memory usage < 30%
  • Network utilization minimal

AWS Compute Optimizer

Free service providing right-sizing recommendations:

aws compute-optimizer get-ec2-instance-recommendations \
  --instance-arns arn:aws:ec2:ap-southeast-2:123456789012:instance/i-1234567890abcdef0

Provides:

  • Current instance type and cost
  • Recommended instance type
  • Projected savings
  • Performance risk assessment

Downsizing Process

  1. Identify candidates: Consistently underutilised instances
  2. Test in non-production: Verify performance with smaller size
  3. Monitor closely: Watch for performance degradation
  4. Implement in production: During maintenance window
  5. Validate: Confirm performance remains acceptable

Typical savings: 20-40% per right-sized instance

Strategy 2: Instance Scheduling

Stop instances when not needed.

Business Hours Schedule

For development and testing:

# lambda_function.py
import boto3
import os
from datetime import datetime

ec2 = boto3.client('ec2')

def lambda_handler(event, context):
    # Sydney timezone (AEDT/AEST)
    current_hour = datetime.now().hour
    current_day = datetime.now().weekday()  # 0 = Monday, 6 = Sunday

    # Find instances with Schedule tag
    instances = ec2.describe_instances(
        Filters=[
            {'Name': 'tag:Schedule', 'Values': ['business-hours']}
        ]
    )

    to_start = []
    to_stop = []

    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            instance_id = instance['InstanceId']
            state = instance['State']['Name']

            # Business hours: Mon-Fri, 8 AM - 6 PM
            is_business_hours = (
                current_day < 5 and  # Monday-Friday
                8 <= current_hour < 18  # 8 AM - 6 PM
            )

            if is_business_hours and state == 'stopped':
                to_start.append(instance_id)
            elif not is_business_hours and state == 'running':
                to_stop.append(instance_id)

    if to_start:
        ec2.start_instances(InstanceIds=to_start)
        print(f"Started instances: {to_start}")

    if to_stop:
        ec2.stop_instances(InstanceIds=to_stop)
        print(f"Stopped instances: {to_stop}")

    return {
        'statusCode': 200,
        'started': len(to_start),
        'stopped': len(to_stop)
    }

Schedule Lambda with EventBridge (hourly):

{
  "schedule": "cron(0 * * * ? *)"
}

Savings: 65-75% on scheduled instances (running 50 hours/week instead of 168)

AWS Instance Scheduler

Pre-built solution from AWS:

  • Supports EC2 and RDS
  • Flexible schedules
  • Multiple time zones
  • DynamoDB-based configuration
  • CloudFormation deployment

Use case: Large environments with complex scheduling needs

Strategy 3: Spot Instances

Up to 90% discount compared to On-Demand.

When to Use Spot

Perfect for:

  • Batch processing
  • Data analysis
  • CI/CD build servers
  • Rendering farms
  • Web scraping
  • Stateless applications
  • Fault-tolerant systems

Not suitable for:

  • Databases
  • Stateful applications (without proper handling)
  • Applications requiring guaranteed availability
  • Long-running processes that can’t checkpoint

Spot Best Practices

1. Diversify Instance Types

Don’t rely on single instance type:

{
  "InstanceTypes": [
    "m6i.large",
    "m5.large",
    "m5a.large",
    "m5n.large"
  ],
  "AllocationStrategy": "price-capacity-optimized"
}

2. Handle Interruptions Gracefully

Listen for 2-minute warning:

#!/bin/bash
# Check Spot instance termination notice
TERMINATION_NOTICE=$(curl -s http://169.254.169.254/latest/meta-data/spot/instance-action)

if [ -n "$TERMINATION_NOTICE" ]; then
    echo "Spot instance terminating"
    # Graceful shutdown
    # - Save state
    # - Drain connections
    # - Deregister from load balancer
    systemctl stop myapp
fi

3. Use Spot Fleet or Auto Scaling Groups

Maintain capacity despite interruptions:

# Auto Scaling Group with mixed instances
MixedInstancesPolicy:
  InstancesDistribution:
    OnDemandBaseCapacity: 2
    OnDemandPercentageAboveBaseCapacity: 20
    SpotAllocationStrategy: price-capacity-optimized
  LaunchTemplate:
    LaunchTemplateSpecification:
      LaunchTemplateId: lt-1234567890abcdef0
      Version: $Latest
    Overrides:
      - InstanceType: m6i.large
      - InstanceType: m5.large
      - InstanceType: m5a.large

80% Spot, 20% On-Demand for resilience.

Spot Placement Score

Evaluate likelihood of getting/maintaining Spot capacity:

aws ec2 get-spot-placement-scores \
  --instance-types m6i.large m5.large m5a.large \
  --target-capacity 10 \
  --region ap-southeast-2

Choose instance types with highest scores.

Strategy 4: Savings Plans and Reserved Instances

Commit to usage, save 30-75%.

EC2 Instance Savings Plans

Most flexible Savings Plan:

Commitment: $X per hour for 1 or 3 years Discount: 30-55% (Sydney region) Flexibility:

  • Change instance family
  • Change instance size
  • Change OS
  • Change tenancy
  • Works across regions (at lower discount)

Best for: Variable workloads, uncertain future needs

Compute Savings Plans

Broadest Savings Plan:

Commitment: $X per hour Discount: 35-60% Flexibility:

  • EC2, Fargate, Lambda
  • All instance families
  • All regions

Best for: Mixed compute workloads

Reserved Instances

Specific instance type commitment:

Commitment: Specific instance type and region
Discount: 40-75%
Flexibility:

  • Instance size flexibility within family
  • AZ flexibility (regional RIs)
  • Can sell on RI Marketplace

Best for: Predictable, steady-state workloads

Choosing the Right Option

Scenario 1: Production web servers (consistent load) → EC2 Instance Savings Plan (flexibility to change instance types)

Scenario 2: Mixed workload (EC2 + Lambda + Fargate) → Compute Savings Plan (covers all compute)

Scenario 3: Production database (RDS or self-managed) → Reserved Instance (highest discount, predictable usage)

Scenario 4: Variable workload → Partial Savings Plan (60-70% coverage) + On-Demand/Spot for spikes

Coverage Analysis

aws ce get-reservation-coverage \
  --time-period Start=2025-10-01,End=2025-11-01 \
  --granularity MONTHLY

Target coverage: 70-80% of baseline usage Leave uncovered: 20-30% for growth and flexibility

Strategy 5: Graviton Instances

AWS Graviton (ARM-based) processors offer better price-performance.

Graviton Benefits

  • 20-40% better price-performance than x86
  • Up to 60% lower cost for similar performance
  • Better energy efficiency

Graviton Instance Families

  • t4g: Burstable (most popular migration target)
  • m7g: General purpose
  • c7g: Compute optimised
  • r7g: Memory optimised

Migration Considerations

Easy migrations:

  • Java applications (JVM is platform-agnostic)
  • Python, Ruby, Node.js, Go
  • Containerized applications
  • Amazon Linux 2, Ubuntu, Debian

Harder migrations:

  • Windows applications (not supported)
  • Legacy compiled binaries
  • Software without ARM support

Example savings:

m6i.large:  $0.125/hour
m7g.large:  $0.0896/hour (28% cheaper, better performance)

Annual savings per instance: $250
For 100 instances: $25,000/year

Strategy 6: Auto Scaling

Scale capacity based on demand.

Target Tracking Scaling

Maintain specific metric:

{
  "TargetValue": 60.0,
  "PredefinedMetricSpecification": {
    "PredefinedMetricType": "ASGAverageCPUUtilization"
  },
  "TargetTrackingScalingPolicyConfiguration": {
    "TargetValue": 60.0,
    "ScaleInCooldown": 300,
    "ScaleOutCooldown": 60
  }
}

Result: Maintain 60% CPU utilization, automatically add/remove instances

Scheduled Scaling

Predictable traffic patterns:

aws autoscaling put-scheduled-update-group-action \
  --auto-scaling-group-name my-asg \
  --scheduled-action-name scale-up-morning \
  --recurrence "0 8 * * 1-5" \
  --min-size 10 \
  --max-size 20 \
  --desired-capacity 15

aws autoscaling put-scheduled-update-group-action \
  --auto-scaling-group-name my-asg \
  --scheduled-action-name scale-down-evening \
  --recurrence "0 18 * * 1-5" \
  --min-size 2 \
  --max-size 10 \
  --desired-capacity 4

Savings: Run minimal capacity during off-peak hours

Predictive Scaling

Machine learning-based forecasting:

{
  "MetricSpecifications": [{
    "TargetValue": 60.0,
    "PredefinedMetricPairSpecification": {
      "PredefinedMetricType": "ASGCPUUtilization"
    }
  }],
  "Mode": "ForecastOnly",
  "SchedulingBufferTime": 600
}

AWS analyzes historical patterns and scales proactively.

Strategy 7: Instance Optimisation

Burstable Instances (T3/T4g)

For workloads with variable CPU usage:

How they work:

  • Baseline CPU performance (e.g., 20% for t3.medium)
  • Accumulate CPU credits during low usage
  • Burst above baseline using credits
  • Much cheaper than fixed-performance instances

Perfect for:

  • Development environments
  • Low-traffic web servers
  • Batch processing
  • Microservices with sporadic load

Cost comparison (Sydney):

t3.medium:   $0.0544/hour (baseline 20%)
m6i.medium:  $0.0625/hour (100% CPU always)

Monitoring: Watch CPUCreditBalance in CloudWatch

EBS-Optimized Instances

For I/O-intensive workloads, ensure EBS optimisation is enabled (most modern instances have it by default).

Enhanced Networking

Free performance improvement - ensure instances support:

  • Elastic Network Adapter (ENA)
  • Higher bandwidth
  • Lower latency
  • Lower jitter

Monitoring and Governance

Cost Allocation Tags

Tag all instances:

{
  "Name": "web-server-prod-01",
  "Environment": "production",
  "Application": "customer-portal",
  "Owner": "platform-team",
  "CostCenter": "engineering",
  "Schedule": "24x7"
}

CloudWatch Dashboards

Monitor costs in real-time:

  • Instance count by type
  • Total compute cost
  • Savings Plan/RI coverage
  • Spot usage percentage

Cost Anomaly Detection

Alert on unexpected spending:

aws ce create-anomaly-monitor \
  --anomaly-monitor '{
    "MonitorName": "EC2-Cost-Monitor",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "SERVICE",
    "MonitorSpecification": {
      "Dimensions": {
        "Key": "SERVICE",
        "Values": ["Amazon Elastic Compute Cloud - Compute"]
      }
    }
  }'

EC2 Cost Optimisation Checklist

Immediate actions:

  • Identify and stop unused instances
  • Enable detailed monitoring for right-sizing analysis
  • Implement instance scheduling for dev/test
  • Review and delete old AMIs and snapshots

30-day actions:

  • Right-size oversized instances
  • Purchase Savings Plans for baseline usage
  • Migrate workloads to Graviton where possible
  • Implement Auto Scaling

90-day actions:

  • Migrate appropriate workloads to Spot
  • Optimize Auto Scaling policies
  • Review and optimise EBS volumes
  • Implement cost dashboards

Ongoing:

  • Monthly cost reviews
  • Quarterly Savings Plan coverage analysis
  • Continuous right-sizing
  • Regular optimisation reviews

Conclusion

EC2 cost optimisation combines multiple strategies - right-sizing, scheduling, Spot instances, Savings Plans, Graviton migration, and Auto Scaling. Start with quick wins like stopping unused instances and implementing schedules, then progress to more sophisticated strategies.

For Australian businesses, EC2 optimisation can reduce compute costs by 40-70% while maintaining or improving performance and reliability.

CloudPoint specialises in EC2 cost optimisation. We analyze your environment, model cost reduction scenarios, and implement sustainable optimisation strategies. Contact us for an EC2 cost assessment.


Want to Optimise Your EC2 Costs?

CloudPoint analyses your EC2 usage and implements right-sizing, Reserved Instances, and Savings Plans strategies. Get in touch to start saving.

Learn more about our Cost Optimisation service →