Terraform Advanced — Locals and Conditionals

1 minute read

Precompute complex expressions with locals and control resource creation with conditionals.


Locals — Precomputed Expressions

locals {
  # Derive values once, use everywhere
  env         = terraform.workspace
  name_prefix = "${var.project}-${local.env}"

  # Merge default tags with custom tags
  common_tags = merge(
    {
      Project     = var.project
      Environment = local.env
      ManagedBy   = "terraform"
    },
    var.extra_tags
  )

  # Flatten nested data structures
  subnet_config = flatten([
    for az in var.availability_zones : [
      for type in ["public", "private"] : {
        az   = az
        type = type
        cidr = cidrsubnet(var.vpc_cidr, 8, index(var.availability_zones, az) * 2 + (type == "private" ? 1 : 0))
      }
    ]
  ])
}

Conditional Resource Creation

# Create resource only in production
resource "aws_cloudwatch_metric_alarm" "cpu" {
  count = var.environment == "production" ? 1 : 0

  alarm_name          = "${local.name_prefix}-cpu-high"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 2
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = 300
  statistic           = "Average"
  threshold           = 80
}

Conditional Expressions in Attributes

resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = var.environment == "production" ? "m5.xlarge" : "t3.micro"

  root_block_device {
    volume_size = var.environment == "production" ? 100 : 20
    volume_type = var.environment == "production" ? "gp3" : "gp2"
  }

  tags = local.common_tags
}

Anti-Pattern: Over-Using Conditionals

# ❌ Anti-pattern: too many conditionals make code unreadable
resource "aws_instance" "app" {
  instance_type = (
    var.env == "prod" ? "m5.xlarge" :
    var.env == "staging" ? "m5.large" :
    var.env == "dev" ? "t3.medium" :
    "t3.micro"
  )
}

# ✅ Best practice: use a map lookup
variable "instance_types" {
  default = {
    prod    = "m5.xlarge"
    staging = "m5.large"
    dev     = "t3.medium"
  }
}

resource "aws_instance" "app" {
  instance_type = lookup(var.instance_types, var.env, "t3.micro")
}

What’s Next?

Practice HCL patterns.

← try, can, one Practice Exercises →

Updated: