Cloud bills have a way of quietly spiralling. You spin up a few EC2 instances for a project, forget to turn off a dev environment, enable a handful of services “just to test,” and by the end of the quarter, you’re staring at an invoice that makes your finance team ask uncomfortable questions. If you’re running workloads on Amazon Web Services, you’ve probably been there.
The good news: most AWS overspending isn’t inevitable. It’s the result of default configurations, forgotten resources, and mismatched capacity — all fixable without touching your application’s performance. Here’s how to do it.
1. Right-Size Your EC2 Instances
The most common source of waste in AWS is overprovisioned compute resources. When you’re unsure what an application needs, it’s tempting to choose a larger instance type and call it safe. But “safe” often means paying for CPU and memory that sit idle 90% of the time.
Start by enabling AWS Compute Optimiser. It analyses your EC2 utilisation metrics over the past 14 days and surfaces specific downsizing recommendations — not guesses, but data-backed suggestions based on your actual usage patterns. In many cases, moving from an m5.xlarge to an m5.large halves your compute costs with zero impact on throughput.
Also review instance families. If your workload is memory-intensive, an r-series instance will outperform a general-purpose m-series at a lower cost for the same job. Getting the family right matters as much as getting the size right.
2. Use Savings Plans and Reserved Instances Strategically
On-demand pricing is the most expensive way to run AWS. If you have any predictable, steady-state workloads — and most production systems do — you’re leaving money on the table by not committing.
Savings Plans (particularly Compute Savings Plans) offer up to 66% off on-demand rates and apply automatically across EC2, Fargate, and Lambda, regardless of instance type, region, or OS. They’re the most flexible commitment option AWS offers.
Reserved Instances go deeper on discount (up to 72%) but are tied to a specific instance family and region. They’re best for stable, long-running workloads where you’re confident in your architecture for the next one to three years.
A practical approach: cover your baseline load with a 1-year Savings Plan, and let on-demand handle bursts. This way you’re not over-committed, but you’re also not paying the on-demand premium for predictable work.
3. Identify and Eliminate Zombie Resources
Idle and unattached resources are silent cost drivers. A developer spins up an RDS instance to test a feature; the feature ships, and the instance keeps running — and billing — for months.
Run a sweep for:
- Unattached EBS volumes — storage that’s no longer connected to any running instance
- Idle load balancers — ALBs and NLBs with no active targets
- Unused Elastic IPs — AWS charges for allocated IPs that aren’t attached to a running instance
- Stopped EC2 instances — storage and Elastic IP costs still accrue even when the instance is off
- Old snapshots — EBS and RDS snapshots accumulate quickly and are easy to forget.
AWS Cost Explorer and Trusted Advisor will surface many of these automatically. Make this cleanup part of a monthly hygiene ritual, not a once-a-year panic.
4. Optimise Your S3 Storage Classes
S3 is deceptively easy to accumulate. Once data goes in, it tends to stay — in the most expensive storage tier — indefinitely.
AWS offers several storage classes designed for different access patterns:
| S3 Standard | Frequently accessed data |
| S3 Standard-IA | Infrequently accessed, needs fast retrieval |
| S3 Glacier Instant Retrieval | Archive data, millisecond access |
| S3 Glacier Deep Archive | Long-term cold storage, hours to retrieve |
If you’re storing logs, backups, or historical data in Standard, you’re almost certainly overpaying. Use S3 Lifecycle Policies to automatically transition objects to cheaper tiers as they age — for example, moving objects to Standard-IA after 30 days and to Glacier after 90. For data with unpredictable access patterns, S3 Intelligent-Tiering handles this automatically with no retrieval fees.
5. Reduce Data Transfer Costs
Data transfer — especially egress out of AWS — is one of the most overlooked line items. Traffic flowing from your AWS resources to the public internet is billed per GB, and it adds up fast at scale.
A few high-impact moves:
- Use VPC Endpoints for services like S3 and DynamoDB. Traffic routes privately within the AWS network instead of going through a NAT Gateway, eliminating both transfer costs and NAT Gateway processing fees.
- Consolidate traffic through CloudFront for user-facing content. CloudFront’s origin fetch pricing is lower than direct EC2 egress, and caching at the edge reduces the volume of requests hitting your origin altogether.
- Keep traffic in the same Availability Zone where possible. Cross-AZ traffic within the same region is billed at $0.01/GB in each direction — small per request, significant at volume.
6. Leverage Spot Instances for Fault-Tolerant Workloads
Spot Instances let you bid on unused EC2 capacity at discounts of up to 90% off on-demand pricing. The trade-off: AWS can reclaim them with a two-minute warning when that capacity is needed elsewhere.
This makes Spot Instances inappropriate for stateful or latency-sensitive production workloads, but ideal for:
- Batch processing and data pipelines
- CI/CD build jobs
- Machine learning training runs
- Stateless microservices with proper retry logic
Use Spot Fleet or EC2 Auto Scaling Groups with mixed instance policies to spread across multiple instance types and Availability Zones, reducing interruption risk while preserving the discount. For long-running ML training, Spot Instance checkpointing lets you save progress and resume after an interruption without starting from scratch.
7. Set Up Budget Alerts and Cost Allocation Tags
You can’t optimise what you can’t see. Before anything else, make sure you have visibility into where your money is going.
AWS Budgets lets you set thresholds and receive alerts when spending approaches or exceeds your targets. Set alerts at 80% and 100% of your monthly budget, and add forecasted-spend alerts to catch overruns before they happen.
Cost Allocation Tags are essential if you have multiple teams, products, or environments sharing an account (or organisation). Tag every resource with Environment, Team, and Project at a minimum, then activate those tags in Cost Explorer. Suddenly, you can see that the data science team is responsible for 40% of your EC2 spend, or that your staging environment costs nearly as much as production — insights that are impossible without tagging.
8. Optimise Lambda and Serverless Costs
Lambda pricing is based on the number of invocations and the duration of each execution (in GB-seconds, combining memory allocation and runtime). There are two levers here:
Memory allocation directly affects both cost and performance. Lambda allocates CPU proportionally to memory, so an underpowered function may run for longer, costing the same or more than a better-provisioned one. Use AWS Lambda Power Tuning (an open-source tool) to find the memory setting that minimises cost per invocation for your specific workload — often it’s neither the minimum nor the maximum.
Architecture patterns also matter. If a Lambda function is invoked millions of times per month for a consistent, predictable workload, it may be cheaper to run that logic on a small EC2 instance or Fargate container instead. Serverless isn’t always the most cost-effective choice at high volume.
9. Review and Consolidate CloudWatch Logs and Metrics
CloudWatch is genuinely useful, but its default configuration is often more aggressive than necessary. Logs are retained indefinitely unless you explicitly set a retention period, and high-resolution custom metrics cost significantly more than standard ones.
Quick wins:
- Set log retention policies on all log groups. Most teams don’t need application logs older than 30–90 days; compliance logs can be exported to S3 Glacier at a fraction of the cost.
- Audit your custom metrics and eliminate any that aren’t actively driving decisions or alerts.
- Review CloudWatch dashboards and alarms for anything referencing resources that no longer exist.
10. Use AWS Organisations and Control Tower for Multi-Account Governance
If you’re running multiple AWS accounts, consolidated billing through AWS Organisations automatically aggregates usage across accounts for volume pricing tiers. Your S3, EC2, and data transfer usage is pooled, so you reach lower pricing tiers faster than any single account would on its own.
Beyond cost, Organisations lets you apply Service Control Policies (SCPs) to restrict which regions or services teams can use — preventing someone from accidentally spinning up expensive GPU instances in a region you don’t support, or enabling services that generate unexpected costs.
Putting It All Together
Cost optimisation on AWS isn’t a single project with a finish line — it’s an ongoing practice. The most effective approach combines quick wins (right-sizing, removing zombies, fixing storage classes) with structural habits (tagging, budgets, regular audits) and architectural decisions (Savings Plans, Spot, endpoint routing).
Start with Compute Optimiser and Cost Explorer to surface your biggest waste. Fix the obvious things first. Then build the tagging and alerting infrastructure that makes future optimisation possible without a manual investigation every quarter.
Hi, this is a comment.
To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
Commenter avatars come from Gravatar.