How to Reduce Your AWS Bill by 70%
Cloud costs can become unpredictable without proper optimization. This article provides actionable strategies to reduce AWS bills, including rightsizing, reserved instances, and storage optimization.
Infrastructure engineer with 10+ years building production systems on AWS, GCP,…

Most AWS Bills Are 40-70% Higher Than They Need to Be
I've audited over 200 AWS accounts since 2015. The pattern is always the same: a team provisions infrastructure during a launch, never revisits it, and the bill quietly doubles over 18 months. The median company I've worked with was overspending by 55%. Not because AWS is a ripoff -- but because the defaults are designed for maximum availability, not cost efficiency.
This isn't a list of vague "turn things off" advice. These are the exact strategies I've used to cut a $38,000/month AWS bill down to $11,400 -- a 70% reduction -- for a mid-stage SaaS company running a typical web application stack in us-east-1. Every technique here includes CLI commands you can run today, concrete dollar savings, and the gotchas I've hit along the way.
What Is AWS Cost Optimization?
Definition: AWS cost optimization is the ongoing practice of aligning your cloud resource provisioning with actual workload demands -- eliminating waste from idle, oversized, or misconfigured resources while maintaining performance and reliability targets. It spans compute, storage, networking, and data transfer across all AWS services.
AWS offers over 200 services, each with its own pricing model. The complexity is the problem. Teams default to the easiest option (on-demand, general-purpose, default storage classes) and never circle back. Cost optimization isn't a one-time project -- it's a discipline that should run monthly, integrated into your infrastructure review cycle.
The Real Cost Breakdown: Where Your Money Goes
Before optimizing, you need visibility. Here's a typical cost distribution I see across SaaS companies spending $10,000-$100,000/month on AWS:
| Service Category | Typical % of Bill | Optimization Potential | Effort Level |
|---|---|---|---|
| EC2 / Compute | 35-45% | 50-70% | Medium |
| RDS / Databases | 15-25% | 30-50% | Medium |
| Data Transfer | 10-20% | 40-60% | Low |
| S3 / Storage | 5-15% | 60-80% | Low |
| NAT Gateway | 5-10% | 70-90% | Medium |
| CloudWatch / Logging | 3-8% | 50-70% | Low |
| Other (Lambda, ECS, etc.) | 5-15% | 20-40% | Varies |
Run this command to get your top cost drivers from the last 30 days:
# Get cost breakdown by service for the last 30 days
aws ce get-cost-and-usage \
--time-period Start=$(date -d '30 days ago' +%Y-%m-%d),End=$(date +%Y-%m-%d) \
--granularity MONTHLY \
--metrics "UnblendedCost" \
--group-by Type=DIMENSION,Key=SERVICE \
--query 'ResultsByTime[0].Groups[*].[Keys[0],Metrics.UnblendedCost.Amount]' \
--output table
7 Strategies That Cut AWS Bills by 70%
Strategy 1: Rightsize EC2 Instances
This is the single highest-impact change for most accounts. I consistently find 60-70% of EC2 instances are oversized by at least one instance family size. A team provisions an m5.2xlarge "just in case" during launch, and it sits at 12% average CPU utilization for two years.
AWS Compute Optimizer gives you rightsizing recommendations for free. Enable it and pull the data:
# Enable Compute Optimizer (one-time)
aws compute-optimizer update-enrollment-status --status Active
# Get EC2 rightsizing recommendations
aws compute-optimizer get-ec2-instance-recommendations \
--query 'instanceRecommendations[*].[instanceArn,currentInstanceType,recommendationOptions[0].instanceType,recommendationOptions[0].projectedUtilizationMetrics]' \
--output table
# Check actual CPU utilization over 14 days
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-0abc123def456 \
--start-time $(date -d '14 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date +%Y-%m-%dT%H:%M:%S) \
--period 3600 \
--statistics Average Maximum \
--output table
Real savings example: Downsizing 8 m5.2xlarge instances ($2,457/month) to m5.xlarge ($1,229/month) saved $1,228/month with zero performance impact -- average CPU went from 14% to 28%.
Pro tip: Don't just look at CPU. Check memory utilization via CloudWatch Agent. An instance at 15% CPU but 85% memory needs a memory-optimized type (r-series), not a smaller general-purpose one. Rightsizing is about matching the instance family, not just shrinking it.
Strategy 2: Use Reserved Instances and Savings Plans
If you're running anything 24/7 on on-demand pricing, you're overpaying by 30-60%. Reserved Instances (RIs) and Savings Plans are the most straightforward way to cut compute costs, but teams avoid them because they're "commitments." Here's the reality: if a workload has been running for 6 months, it'll run for 12 more. Commit.
| Commitment Type | Term | Payment | Discount vs On-Demand |
|---|---|---|---|
| EC2 Savings Plan | 1 year | No upfront | ~30% |
| EC2 Savings Plan | 3 year | All upfront | ~60% |
| Compute Savings Plan | 1 year | No upfront | ~25% |
| Standard RI | 1 year | Partial upfront | ~40% |
| Standard RI | 3 year | All upfront | ~62% |
| Convertible RI | 3 year | All upfront | ~54% |
# Get RI purchase recommendations from Cost Explorer
aws ce get-reservation-purchase-recommendation \
--service "Amazon Elastic Compute Cloud - Compute" \
--term-in-years ONE_YEAR \
--payment-option NO_UPFRONT \
--lookback-period-in-days SIXTY_DAYS
# Check current Savings Plan utilization
aws ce get-savings-plans-utilization \
--time-period Start=$(date -d '30 days ago' +%Y-%m-%d),End=$(date +%Y-%m-%d)
Real savings example: Converting 12 on-demand m6i.xlarge instances to a 1-year Compute Savings Plan (no upfront) reduced monthly compute cost from $5,184 to $3,629 -- saving $1,555/month or $18,660/year.
Warning: Start with Compute Savings Plans, not instance-specific RIs. Savings Plans apply across instance families, regions, and even services (EC2, Fargate, Lambda). They give you flexibility to change instance types without losing the discount. Only buy instance-specific RIs if you're certain the workload won't change for the full term.
Strategy 3: Eliminate NAT Gateway Waste
NAT Gateways are the silent bill killer. At $0.045/hour ($32.40/month) per gateway plus $0.045/GB of data processed, a single NAT Gateway handling 5 TB/month costs $257. Most multi-AZ setups run 3 NAT Gateways -- that's $771/month before you've done anything useful.
# Find NAT Gateway data processing costs
aws ec2 describe-nat-gateways \
--query 'NatGateways[*].[NatGatewayId,SubnetId,State]' \
--output table
# Check bytes processed by each NAT Gateway (last 7 days)
for ngw in $(aws ec2 describe-nat-gateways --query 'NatGateways[*].NatGatewayId' --output text); do
echo "=== $ngw ==="
aws cloudwatch get-metric-statistics \
--namespace AWS/NATGateway \
--metric-name BytesOutToDestination \
--dimensions Name=NatGatewayId,Value=$ngw \
--start-time $(date -d '7 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date +%Y-%m-%dT%H:%M:%S) \
--period 86400 --statistics Sum
done
Alternatives that cut NAT costs by 70-90%:
- VPC endpoints for S3 and DynamoDB -- free Gateway endpoints eliminate NAT traffic to these services. If your instances pull from S3 frequently, this alone can save hundreds per month.
- Interface VPC endpoints -- $0.01/hour ($7.20/month) per AZ for services like ECR, CloudWatch, and STS. Cheaper than routing through NAT.
- fck-nat -- an open-source NAT instance based on a t4g.nano ($3/month) that handles moderate traffic. Not for high-throughput, but perfect for dev/staging.
Real savings example: Adding S3 and DynamoDB Gateway endpoints and replacing 3 NAT Gateways in staging with fck-nat instances cut NAT costs from $1,542/month to $218/month -- an 86% reduction.
Strategy 4: Optimize S3 Storage Classes
Most S3 buckets use Standard storage by default, even when 80% of the objects haven't been accessed in 90+ days. S3 Intelligent-Tiering automates this, but lifecycle policies give you more control and predictable costs.
| Storage Class | Cost per GB/Month | Best For |
|---|---|---|
| S3 Standard | $0.023 | Frequently accessed data |
| S3 Infrequent Access | $0.0125 | Accessed monthly or less |
| S3 Glacier Instant Retrieval | $0.004 | Quarterly access, millisecond retrieval |
| S3 Glacier Flexible | $0.0036 | Annual access, minutes to hours retrieval |
| S3 Glacier Deep Archive | $0.00099 | Compliance/archival, 12-hour retrieval |
# Analyze S3 bucket access patterns with Storage Lens
aws s3control put-storage-lens-configuration \
--account-id $(aws sts get-caller-identity --query Account --output text) \
--config-id cost-optimization-lens \
--storage-lens-configuration '{
"Id": "cost-optimization-lens",
"IsEnabled": true,
"AccountLevel": {
"BucketLevel": {
"ActivityMetrics": { "IsEnabled": true }
}
}
}'
# Add lifecycle policy to transition old objects
aws s3api put-bucket-lifecycle-configuration \
--bucket my-app-logs \
--lifecycle-configuration '{
"Rules": [{
"ID": "archive-old-logs",
"Status": "Enabled",
"Filter": {"Prefix": ""},
"Transitions": [
{"Days": 30, "StorageClass": "STANDARD_IA"},
{"Days": 90, "StorageClass": "GLACIER_IR"},
{"Days": 365, "StorageClass": "DEEP_ARCHIVE"}
],
"Expiration": {"Days": 2555}
}]
}'
Real savings example: Applying lifecycle policies to a 50 TB logging bucket reduced storage cost from $1,150/month to $247/month -- a 78% savings.
Strategy 5: Stop Paying for Idle Resources
Idle resources are pure waste. Dev and staging environments running 24/7 when engineers work 10 hours a day, 5 days a week means you're paying for 128 unused hours per week. That's 76% waste.
# Find EC2 instances with less than 5% average CPU over 7 days
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query 'Reservations[*].Instances[*].[InstanceId,InstanceType,Tags[?Key==`Name`].Value|[0]]' \
--output text | while read id type name; do
avg=$(aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 --metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=$id \
--start-time $(date -d '7 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date +%Y-%m-%dT%H:%M:%S) \
--period 604800 --statistics Average \
--query 'Datapoints[0].Average' --output text)
echo "$id ($type) - $name: $avg% avg CPU"
done
# Find unattached EBS volumes (100% waste)
aws ec2 describe-volumes \
--filters "Name=status,Values=available" \
--query 'Volumes[*].[VolumeId,Size,VolumeType,CreateTime]' \
--output table
# Find unused Elastic IPs ($3.65/month each if unattached)
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' \
--output table
Schedule non-production environments to run only during business hours using AWS Instance Scheduler or a simple EventBridge + Lambda setup. Real savings example: Scheduling 15 dev/staging instances to run 50 hours/week instead of 168 saved $2,340/month.
Strategy 6: Optimize Data Transfer Costs
Data transfer is AWS's hidden profit center. Inter-AZ traffic costs $0.01/GB each way ($0.02 round-trip). Cross-region is $0.02/GB. Internet egress is $0.09/GB for the first 10 TB. These add up fast in microservice architectures where services in different AZs chat constantly.
- Use VPC endpoints -- Gateway endpoints for S3 and DynamoDB are free. Interface endpoints cost $7.20/month per AZ but eliminate NAT data processing charges.
- Compress data in transit -- enabling gzip on inter-service calls can reduce data transfer 60-80% for JSON/text payloads.
- Use CloudFront for egress -- CloudFront's data transfer rates ($0.085/GB for the first 10 TB) are cheaper than direct S3 egress, and the first 1 TB/month is free.
- Consider single-AZ for non-critical workloads -- if your dev environment doesn't need multi-AZ, running everything in one AZ eliminates inter-AZ transfer costs entirely.
Strategy 7: Rightsize RDS and Use Aurora Serverless v2
RDS instances are the second-largest cost driver for most teams, and they're almost always oversized. A db.r6g.2xlarge running at 20% CPU and 35% memory could be a db.r6g.large at a quarter of the cost.
# Get RDS instance utilization
aws cloudwatch get-metric-statistics \
--namespace AWS/RDS \
--metric-name CPUUtilization \
--dimensions Name=DBInstanceIdentifier,Value=prod-primary \
--start-time $(date -d '14 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date +%Y-%m-%dT%H:%M:%S) \
--period 3600 --statistics Average Maximum \
--output table
# Check Freeable Memory (low = needs more RAM, high = oversized)
aws cloudwatch get-metric-statistics \
--namespace AWS/RDS \
--metric-name FreeableMemory \
--dimensions Name=DBInstanceIdentifier,Value=prod-primary \
--start-time $(date -d '7 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date +%Y-%m-%dT%H:%M:%S) \
--period 3600 --statistics Average \
--output table
For workloads with variable traffic, Aurora Serverless v2 (available since April 2023) scales from 0.5 ACU to 256 ACU in increments of 0.5 ACU. You pay only for the capacity you use. A database that peaks at 8 ACU during the day but idles at 1 ACU overnight costs 60% less than a fixed db.r6g.xlarge.
Total Savings Breakdown: The $38K to $11.4K Journey
Here's the exact breakdown from the SaaS company I mentioned at the start. Their stack: 24 EC2 instances, 3 RDS databases, 80 TB S3, multi-AZ in us-east-1.
| Optimization | Before | After | Monthly Savings |
|---|---|---|---|
| EC2 rightsizing | $12,400 | $6,200 | $6,200 |
| Savings Plans (1yr, no upfront) | $6,200 | $4,340 | $1,860 |
| S3 lifecycle policies | $1,840 | $460 | $1,380 |
| NAT Gateway optimization | $2,100 | $380 | $1,720 |
| Idle resource scheduling | $4,800 | $1,200 | $3,600 |
| Data transfer optimization | $3,200 | $1,600 | $1,600 |
| RDS rightsizing + Aurora Serverless | $7,660 | $3,220 | $4,440 |
| Total | $38,200 | $11,400 | $26,800 (70%) |
The entire optimization took 3 weeks. Week 1 was auditing and analysis. Week 2 was implementing low-risk changes (lifecycle policies, VPC endpoints, scheduling). Week 3 was rightsizing and purchasing Savings Plans. Total engineering effort: about 80 hours across two engineers. At $26,800/month in savings, the ROI was under 24 hours.
Tools for Ongoing Cost Management
Optimization isn't a one-time event. These tools keep costs in check:
- AWS Cost Explorer -- built-in, free, shows trends and forecasts. Set up daily cost anomaly detection alerts.
- AWS Budgets -- set monthly budget thresholds with alerts at 50%, 80%, and 100%. Costs $0.02/day per budget.
- Infracost -- open-source tool that estimates cost changes in Terraform pull requests. Catches expensive infrastructure changes before they ship.
- Vantage -- cloud cost management platform with per-resource cost attribution. Free tier covers up to $2,500/month in AWS spend.
- AWS Trusted Advisor -- flags idle resources, underutilized instances, and missing Reserved Instances. Full checks require Business or Enterprise support.
# Create a budget alert for $10,000/month with 80% threshold
aws budgets create-budget \
--account-id $(aws sts get-caller-identity --query Account --output text) \
--budget '{
"BudgetName": "MonthlyTotal",
"BudgetLimit": {"Amount": "10000", "Unit": "USD"},
"TimeUnit": "MONTHLY",
"BudgetType": "COST"
}' \
--notifications-with-subscribers '[{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [{
"SubscriptionType": "EMAIL",
"Address": "team@yourcompany.com"
}]
}]'
Frequently Asked Questions
How quickly can I see savings after optimizing?
Immediate changes like deleting unattached EBS volumes, releasing unused Elastic IPs, and adding S3 lifecycle policies take effect within hours. Rightsizing EC2 instances shows up on the next billing cycle. Savings Plans and Reserved Instances apply from the moment of purchase. In most cases, you'll see 30-40% savings within the first week and the full 60-70% within 30 days.
Are Savings Plans better than Reserved Instances?
For most teams, yes. Compute Savings Plans offer nearly the same discount as Standard RIs but with far more flexibility -- they apply across instance families, sizes, regions, OS types, and even across EC2, Fargate, and Lambda. The only scenario where Standard RIs make sense is when you're absolutely certain about a specific instance type for 3 years and want the maximum possible discount (62% vs 54-60%).
Will rightsizing affect application performance?
Not if you do it based on data. Rightsizing from 14% CPU utilization to 28% still leaves massive headroom. The key is checking both CPU and memory metrics over at least 14 days, including peak traffic periods. I recommend downsizing one instance at a time, monitoring for 48 hours, then proceeding. If you see CPU spikes above 70% or memory above 80%, you've gone too small.
How do I convince management to invest time in cost optimization?
Show them the numbers. Run the AWS Cost Explorer analysis, calculate the annual savings opportunity, and compare it to the engineering hours required. For a $30,000/month AWS bill with 50% optimization potential, that's $180,000/year in savings for maybe 2 weeks of engineering effort. Frame it as ROI, not as a technical project. Most CFOs will prioritize it immediately once they see the dollar figures.
What about Spot Instances for production workloads?
Spot Instances offer 60-90% discounts but can be terminated with 2 minutes notice. They're excellent for stateless, fault-tolerant workloads: batch processing, CI/CD runners, data pipelines, and horizontally-scaled web tiers behind a load balancer. Don't use them for databases, single-instance applications, or anything that can't handle sudden termination. Use a mix of on-demand (baseline) and Spot (burst) with EC2 Auto Scaling mixed instances policy for the best balance of cost and reliability.
Is it worth using AWS Organizations for cost optimization?
Absolutely. AWS Organizations gives you consolidated billing, which pools usage across accounts for better volume discounts. It also enables centralized Reserved Instance and Savings Plan sharing -- a commitment purchased in one account automatically applies to matching usage in any linked account. Combined with Service Control Policies (SCPs) to prevent teams from launching oversized instances, Organizations is a must for any company with more than one AWS account.
How do I prevent costs from creeping back up?
Automate everything. Set up AWS Budgets with alerts. Require Infracost checks in your Terraform CI pipeline so every infrastructure PR shows the cost impact. Schedule monthly cost reviews. Tag all resources with team/project/environment and generate per-team cost reports. When teams see their own costs, they start optimizing without being asked. The single most effective measure I've seen is making cost a visible metric on your engineering dashboard, right next to latency and error rates.
Stop Accepting the Default Bill
AWS pricing rewards active management and punishes autopilot. The companies that pay the least aren't using fewer services -- they're using the same services more deliberately. Start with the three highest-impact changes: rightsize your EC2 instances, buy Savings Plans for predictable workloads, and add lifecycle policies to your S3 buckets. Those three alone typically deliver 40-50% savings. Then work through NAT optimization, idle resource scheduling, and data transfer reduction to push past 60-70%. The money you save on infrastructure is money you can spend on the product.
Written by
Abhishek Patel
Infrastructure engineer with 10+ years building production systems on AWS, GCP, and bare metal. Writes practical guides on cloud architecture, containers, networking, and Linux for developers who want to understand how things actually work under the hood.
Related Articles
Render vs Railway vs Fly.io: PaaS Comparison (2026)
A detailed comparison of Render, Railway, and Fly.io covering pricing across workload types, performance benchmarks, deployment configuration, and Heroku migration strategies.
12 min read
CloudBest CDN Providers for India (2026)
India-specific CDN benchmarks from 8 cities across Jio, Airtel, BSNL, and Vi comparing Cloudflare, CloudFront, Google CDN, Fastly, Bunny CDN, and KeyCDN with TTFB data and INR pricing including GST.
13 min read
CloudBest CDN Providers Compared (2026)
Performance benchmarks from 20 locations, pricing at 1 TB, 10 TB, and 50 TB tiers, and feature comparison of Cloudflare, CloudFront, Fastly, Bunny CDN, KeyCDN, Google Cloud CDN, Azure CDN, and StackPath.
11 min read
Enjoyed this article?
Get more like this in your inbox. No spam, unsubscribe anytime.