🎯 Goal: Move beyond basic resources β†’ use meta-arguments to build dynamic, reliable, production-grade configs.

βœ… You’ll master:


🧠 Why Meta-Arguments Matter

❌ Without meta-arguments:

β†’ 10 copies of aws_s3_bucket blocks

β†’ Resource creation order = guesswork

β†’ Accidental terraform destroy = production outage

βœ… With meta-arguments:

β†’ DRY: One block β†’ N resources

β†’ Reliable: Control dependencies & lifecycle

β†’ Safe: Guardrails against human error


πŸ“¦ Meta-Arguments Cheat Sheet

Meta-Argument Input Type Use Case Stability Production Ready?
count number Fixed N identical resources (e.g., dev instances) ⚠️ Low (index drift) ❌ Avoid in prod
for_each map / set(string) Named resources (e.g., env-specific buckets) βœ… High (key-based) βœ… Preferred
depends_on [resource] Hidden dependencies (e.g., IAM β†’ S3) β€” βœ… Use sparingly
lifecycle Block Protect resources, ignore drift β€” βœ… Critical for prod

🎯 Golden Rule:

β€œUse for_each 90% of the time β€” count only for simple, temporary resources.”


✏️ Hands-On: count vs for_each β€” S3 Bucket Lab

πŸ”Ή variables.tf β€” Input Data

# πŸ”Έ List (for `count`)
variable "bucket_names_list" {
  type    = list(string)
  default = ["dev-logs", "staging-logs"]
}

# πŸ”Έ Set (for `for_each`)
variable "bucket_names_set" {
  type = set(string)
  default = toset(["prod-logs", "dr-logs"])  # ← Dedupes automatically
}

# πŸ”Έ Map (for advanced `for_each`)
variable "bucket_configs" {
  type = map(object({
    tags  = map(string)
    acl   = string
  }))
  default = {
    "audit" = {
      tags = { Purpose = "Compliance" },
      acl  = "private"
    }
    "backup" = {
      tags = { Purpose = "Disaster Recovery" },
      acl  = "private"
    }
  }
}


1️⃣ count β€” Simple, but Fragile

main.tf