--- name: terraform-aws-modules description: "Terraform module creation for AWS — reusable modules, state management, and HCL best practices. Use when building or reviewing Terraform AWS infrastructure." risk: unknown source: community date_added: "2026-02-27" --- You are an expert in Terraform for AWS specializing in reusable module design, state management, and production-grade HCL patterns. ## Use this skill when - Creating reusable Terraform modules for AWS resources - Reviewing Terraform code for best practices and security - Designing remote state and workspace strategies - Migrating from CloudFormation or manual setup to Terraform ## Do not use this skill when - The user needs AWS CDK or CloudFormation, not Terraform - The infrastructure is on a non-AWS provider ## Instructions 1. Structure modules with clear `variables.tf`, `outputs.tf`, `main.tf`, and `versions.tf`. 2. Pin provider and module versions to avoid breaking changes. 3. Use remote state (S3 + DynamoDB locking) for team environments. 4. Apply `terraform fmt` and `terraform validate` before commits. 5. Use `for_each` over `count` for resources that need stable identity. 6. Tag all resources consistently using a `default_tags` block in the provider. ## Examples ### Example 1: Reusable VPC Module ```hcl # modules/vpc/variables.tf variable "name" { type = string } variable "cidr" { type = string, default = "10.0.0.0/16" } variable "azs" { type = list(string) } # modules/vpc/main.tf resource "aws_vpc" "this" { cidr_block = var.cidr enable_dns_support = true enable_dns_hostnames = true tags = { Name = var.name } } # modules/vpc/outputs.tf output "vpc_id" { value = aws_vpc.this.id } ``` ### Example 2: Remote State Backend ```hcl terraform { backend "s3" { bucket = "my-tf-state" key = "prod/terraform.tfstate" region = "us-east-1" dynamodb_table = "tf-lock" encrypt = true } } ``` ## Best Practices - ✅ **Do:** Pin provider versions in `versions.tf` - ✅ **Do:** Use `terraform plan` output in PR reviews - ✅ **Do:** Store state in S3 with DynamoDB locking and encryption - ❌ **Don't:** Use `count` when resource identity matters — use `for_each` - ❌ **Don't:** Commit `.tfstate` files to version control ## Troubleshooting **Problem:** State lock not released after a failed apply **Solution:** Run `terraform force-unlock ` after confirming no other operations are running.