The 5 Terraform Mistakes Costing You $10K+/Month on AWS
Most teams are bleeding cloud money from the same five Terraform anti-patterns. I've audited dozens of AWS accounts and these show up every single time. Here's what they are and the exact fixes.
---
1. No Default Tags = No Cost Visibility
If you can't attribute costs to teams, projects, or environments, you can't optimize anything. Most teams add tags inconsistently or not at all.
The fix:
provider "aws" {
region = "us-east-1"
default_tags {
tags = {
Environment = var.environment
Team = var.team_name
CostCenter = var.cost_center
ManagedBy = "terraform"
}
}
}This applies tags to every resource automatically. No more unattributed costs.
---
2. CloudWatch Logs Set to "Never Expire"
This is the single most common waste I see. Lambda, ECS, and API Gateway all generate logs. The default retention? Forever.
A moderately busy Lambda function generates 5-10 GB/month of logs. At $0.03/GB storage, that's $1.80/year per function. Multiply by 200 functions across 3 environments, and you're paying $1,000+/year for logs nobody reads.
resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/${var.function_name}"
retention_in_days = 14 # or 30 for production
}---
3. Using gp2 Instead of gp3 for EBS Volumes
AWS made gp3 the default for new volumes, but most Terraform configs still specify gp2 explicitly. gp3 is 20% cheaper with better baseline performance (3,000 IOPS vs 100/GB).
resource "aws_ebs_volume" "data" {
availability_zone = var.az
size = 100
type = "gp3" # NOT gp2
iops = 3000 # Free baseline
throughput = 125 # Free baseline
}For a team with 50 volumes averaging 200GB, switching from gp2 to gp3 saves ~$1,200/year. Zero performance risk.
---
4. NAT Gateways Without Thinking
NAT Gateways cost $0.045/hour ($32.40/month) plus $0.045/GB of data processed. Most teams deploy one per AZ "because the reference architecture said so."
Before deploying a NAT Gateway, ask:
Do these private subnets actually need internet access?
Can you use VPC endpoints for AWS services instead? (S3, DynamoDB, SQS, etc.)
Can you use a single NAT Gateway for non-prod environments?
# VPC endpoints are free or near-free and eliminate NAT data charges
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.s3"
route_table_ids = var.private_route_table_ids
}
resource "aws_vpc_endpoint" "dynamodb" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.region}.dynamodb"
route_table_ids = var.private_route_table_ids
}I've seen teams save $3,000-8,000/month just by adding S3 and DynamoDB VPC endpoints.
---
5. No Environment Scheduling
Running dev, staging, and QA environments 24/7 when they're only used during business hours (roughly 50 hours/week out of 168).
That means 70% of non-prod compute spend is pure waste.
The simplest approach: tag instances with a schedule and use a Lambda + EventBridge to stop/start them.
resource "aws_instance" "dev_server" {
ami = var.ami_id
instance_type = "t3.large"
tags = {
Schedule = "business-hours" # Mon-Fri 8am-6pm
Environment = "dev"
}
}---
Total Potential Savings
Fix | Typical Savings |
|---|---|
CloudWatch log retention | $500-2,000/year |
gp2 → gp3 migration | $1,000-3,000/year |
VPC endpoints vs NAT | $3,000-8,000/month |
Environment scheduling | 70% of non-prod compute |
Cost tag visibility | Enables everything above |
These are not theoretical. These are real numbers from real audits.
If you want the complete framework — all the Terraform modules, automated cost governance, and advanced strategies like spot instances, reserved instances, and multi-cloud arbitrage — that's what the course covers.
