Why AWS Bills Spiral Out of Control
AWS makes it extremely easy to spin up resources and surprisingly difficult to understand exactly what you're paying for. The typical £8,000/month AWS bill we see at SpiderHunts usually breaks down as: 40 to 50% EC2 compute, 15 to 25% RDS, 10 to 20% data transfer (often shocking when teams see this for the first time), 5 to 10% S3 storage, and the remaining 10 to 20% across NAT Gateways, load balancers, and dozens of smaller services.
The root causes are predictable: developers provision "just in case" oversized instances, non-production environments run 24/7 when they're only needed 8 hours a day, snapshots accumulate for years, and nobody audited the EBS volumes that are still attached to terminated instances from 2023. Add in data transfer costs that nobody thought to model, and you have a bill that grows 15 to 20% per year even with constant traffic.
The 5 Cost Optimisation Levers
Lever 1: Right-Sizing
Right-sizing means matching instance size to actual utilisation. AWS Compute Optimizer analyses CloudWatch metrics and recommends instance changes. The tool consistently finds that 60 to 70% of EC2 instances are over-provisioned — often running at under 20% average CPU with under 40% memory utilisation.
Process: export Compute Optimizer recommendations, review the top 20 instances by monthly cost, downsize each by one size class and monitor for 2 weeks. If CPU or memory spikes above 80% sustained, size back up. Repeat. Do the same for RDS — Compute Optimizer covers RDS in its recommendations. A single RDS db.r6g.2xlarge downsized to db.r6g.xlarge saves approximately £200/month.
Lever 2: Reserved Instances and Savings Plans
Compute Savings Plans provide up to 66% discount versus on-demand pricing in exchange for a commitment to a spend level (e.g., £5/hr) for 1 or 3 years. They apply automatically across EC2 instances of any family, size, or region. This is the easiest and most flexible commitment discount.
EC2 Instance Savings Plans provide up to 72% discount for a commitment to a specific instance family in a specific region. Less flexible but higher savings for stable, predictable workloads.
Reserved Instances for RDS, ElastiCache, Redshift, and OpenSearch are still the right mechanism for those services — Savings Plans don't cover them. A 1-year Reserved Instance for RDS saves 30 to 40% versus on-demand. A 3-year reservation saves 50 to 60%.
When each saves more: Use Compute Savings Plans for EC2 if your workload mix changes. Use EC2 Instance Savings Plans if you know your instance family for the next year. Use RDS Reserved Instances for stable database workloads. Never commit more than 70% of your baseline compute spend — leave capacity for growth.
Lever 3: Auto-Scaling
Running fixed-size capacity 24/7 to handle peak load means you're paying for peak capacity even at 3am when traffic is 10% of peak. Auto-scaling with target tracking policies scales instances up during business hours and down overnight, typically saving 25 to 40% on compute costs for applications with predictable traffic patterns.
# Terraform: Auto Scaling Group with target tracking
resource "aws_autoscaling_group" "app" {
name = "app-asg"
vpc_zone_identifier = var.private_subnet_ids
target_group_arns = [aws_lb_target_group.app.arn]
health_check_type = "ELB"
min_size = 2
max_size = 10
desired_capacity = 2
launch_template {
id = aws_launch_template.app.id
version = "$Latest"
}
tag {
key = "Name"
value = "app-instance"
propagate_at_launch = true
}
}
# Target tracking: maintain 60% CPU utilisation
resource "aws_autoscaling_policy" "cpu_tracking" {
name = "cpu-target-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
}
}
# Scheduled scaling: scale down overnight
resource "aws_autoscaling_schedule" "scale_down_night" {
scheduled_action_name = "scale-down-night"
autoscaling_group_name = aws_autoscaling_group.app.name
recurrence = "0 20 * * MON-FRI" # 8pm UTC weekdays
min_size = 1
max_size = 10
desired_capacity = 1
}
resource "aws_autoscaling_schedule" "scale_up_morning" {
scheduled_action_name = "scale-up-morning"
autoscaling_group_name = aws_autoscaling_group.app.name
recurrence = "0 7 * * MON-FRI" # 7am UTC weekdays
min_size = 2
max_size = 10
desired_capacity = 2
}
Lever 4: Storage Tiering
S3 Intelligent-Tiering automatically moves objects between access tiers based on access patterns, at no retrieval cost. For buckets where access patterns are unpredictable, enable Intelligent-Tiering and let AWS optimise automatically. For buckets with predictable patterns (e.g., logs, backups), use explicit S3 Lifecycle Rules.
A typical lifecycle policy: keep objects in Standard for 30 days, move to Standard-IA for days 31 to 90, move to Glacier Instant Retrieval for days 91 to 365, then Glacier Deep Archive or delete after 1 year. This reduces storage costs for long-lived data by 60 to 80%.
For EBS: delete unattached volumes (check for any running EC2 instance association first), convert gp2 volumes to gp3 (20% cheaper, better performance), and implement snapshot lifecycle policies to automatically delete snapshots older than 90 days for non-critical systems.
Lever 5: Data Transfer Costs
Data transfer is the hidden AWS bill killer. AWS charges: £0.09/GB for data leaving the cloud (egress to internet), £0.01/GB for data moving between availability zones (AZ-to-AZ), and £0/GB for data within the same AZ. Across a high-traffic application, AZ-to-AZ transfer costs alone can reach thousands of pounds per month.
NAT Gateway optimisation: each NAT Gateway charges £0.048/GB processed and £0.048/hr per AZ. For traffic that goes from private subnets to AWS services (S3, DynamoDB, Secrets Manager, etc.), use VPC Interface Endpoints or Gateway Endpoints instead — they eliminate the NAT Gateway processing charge. An application making heavy S3 calls can save hundreds of pounds per month by adding a VPC Gateway Endpoint for S3 (which is free).
Real Example: £8,000/month to £4,800
Here is a real-world breakdown from a client engagement at SpiderHunts Technologies. The client was running a SaaS application on AWS at £8,000/month.
| Optimisation | Before | After | Monthly Saving |
|---|---|---|---|
| Compute Savings Plan (1-year) | On-demand EC2: £3,200/mo | Savings Plan: £2,100/mo | £1,100 |
| Right-sizing EC2 (4 instances downsized) | r6g.2xlarge x4 | r6g.xlarge x4 | £520 |
| RDS Reserved Instance (1-year) | On-demand RDS: £1,800/mo | Reserved: £1,260/mo | £540 |
| S3 lifecycle rules (logs + backups) | S3: £480/mo | S3 + tiering: £190/mo | £290 |
| VPC endpoint for S3 (removes NAT GW cost) | NAT GW data: £420/mo | Endpoint: £85/mo | £335 |
| Delete forgotten resources | Unattached EBS, old snapshots, idle EIPs | Removed | £415 |
| Total | £8,000/mo | £4,800/mo | £3,200 (40%) |
Cost Optimisation Actions: Priority Guide
| Action | Typical Saving | Effort | Risk | Priority |
|---|---|---|---|---|
| Compute Savings Plan (1-year) | 30–40% on EC2 | Very low (a few clicks) | Very low | Do immediately |
| Delete forgotten resources | £100–500/mo typical | Low (run audit) | Very low | Do immediately |
| Right-size EC2 and RDS | 15–30% on those services | Medium | Low with monitoring | Week 1–2 |
| S3 Intelligent-Tiering / lifecycle rules | 40–80% on cold data storage | Low | Very low | Week 2 |
| VPC endpoints for S3/DynamoDB | 50–80% on NAT GW data costs | Low | Very low | Week 2 |
| Auto-scaling for variable workloads | 25–40% on compute | Medium | Low with testing | Month 1 |
| Auto-stop dev/staging environments | 60–75% on dev compute | Medium | Low | Month 1 |
| gp2 to gp3 EBS migration | 20% on EBS costs | Very low | Very low | Month 1 |
Cost Monitoring Tools
AWS Cost Explorer provides daily, monthly, and resource-level cost breakdown with filtering by service, region, linked account, and tags. Enable resource-level granularity (there's a small additional cost) to see per-instance spend. Use the Savings Plans and Reserved Instance coverage reports to identify optimisation gaps.
AWS Trusted Advisor (Business or Enterprise support tier) flags idle EC2, underutilised RDS, unassociated Elastic IPs, and other waste across your account. Run monthly and action all findings.
AWS Compute Optimizer analyses 14 days of CloudWatch metrics and provides specific downsize recommendations with projected savings. It covers EC2, EBS, Lambda, ECS, and RDS. Free to use.
Is Your AWS Bill Higher Than It Should Be?
SpiderHunts Technologies offers an AWS cost optimisation audit. We analyse your account, identify waste and savings opportunities, and implement the changes. Most clients see a 25 to 40% reduction within 60 days.
Request an AWS Cost Audit