Reduce AWS Costs With Terraform
Cloud bills grow fast. These Terraform patterns help you build cost-aware infrastructure from the start.
1. Right-Size Instances
variable "instance_sizes" {
default = {
dev = "t3.micro"
staging = "t3.small"
prod = "t3.large"
}
}
resource "aws_instance" "app" {
instance_type = var.instance_sizes[terraform.workspace]
}
2. Use Spot Instances for Non-Critical Workloads
resource "aws_spot_instance_request" "batch" {
ami = data.aws_ami.ubuntu.id
instance_type = "c5.xlarge"
spot_price = "0.05"
wait_for_fulfillment = true
spot_type = "one-time"
tags = { Name = "batch-processor" }
}
Mixed ASG (On-Demand + Spot)
resource "aws_autoscaling_group" "app" {
mixed_instances_policy {
instances_distribution {
on_demand_base_capacity = 1
on_demand_percentage_above_base_capacity = 25
spot_allocation_strategy = "capacity-optimized"
}
launch_template {
launch_template_specification {
launch_template_id = aws_launch_template.app.id
}
override {
instance_type = "t3.medium"
}
override {
instance_type = "t3a.medium"
}
}
}
}
3. Schedule Non-Production Resources
# Stop dev instances at night
resource "aws_autoscaling_schedule" "scale_down" {
autoscaling_group_name = aws_autoscaling_group.dev.name
scheduled_action_name = "scale-down-night"
recurrence = "0 20 * * MON-FRI"
desired_capacity = 0
min_size = 0
max_size = 0
}
resource "aws_autoscaling_schedule" "scale_up" {
autoscaling_group_name = aws_autoscaling_group.dev.name
scheduled_action_name = "scale-up-morning"
recurrence = "0 8 * * MON-FRI"
desired_capacity = 2
min_size = 1
max_size = 4
}
4. Use S3 Lifecycle Rules
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
bucket = aws_s3_bucket.logs.id
rule {
id = "archive-old-logs"
status = "Enabled"
transition {
days = 30
storage_class = "STANDARD_IA"
}
transition {
days = 90
storage_class = "GLACIER"
}
expiration {
days = 365
}
}
}
5. NAT Gateway Alternatives
NAT Gateways cost ~$32/month + data transfer. For dev environments:
# Use a NAT instance instead (~$3/month with t3.nano)
resource "aws_instance" "nat" {
count = terraform.workspace == "prod" ? 0 : 1
ami = data.aws_ami.nat_instance.id
instance_type = "t3.nano"
source_dest_check = false
}
Cost Estimation in CI/CD
Add Infracost to your pipeline:
infracost breakdown --path . --format table
Learn More
- Terraform for Beginners Course — hands-on cost optimization labs
- Terraform By Example Book — real-world patterns
- Terraform Cheat Sheet — quick command reference

