Terraform Advanced — Preconditions & Postconditions

less than 1 minute read

Validate assumptions before creating resources and verify outcomes after.


Preconditions (Terraform 1.2+)

Check assumptions before Terraform creates a resource:

resource "aws_instance" "app" {
  ami           = var.ami_id
  instance_type = var.instance_type

  lifecycle {
    precondition {
      condition     = can(regex("^ami-", var.ami_id))
      error_message = "ami_id must start with 'ami-'"
    }

    precondition {
      condition     = contains(["t3.micro", "t3.small", "m5.large"], var.instance_type)
      error_message = "instance_type must be one of: t3.micro, t3.small, m5.large"
    }
  }
}

Postconditions

Verify outcomes after resource creation:

resource "aws_db_instance" "main" {
  engine               = "postgres"
  engine_version       = "15.4"
  instance_class       = "db.r5.large"
  allocated_storage    = 100
  publicly_accessible  = false

  lifecycle {
    postcondition {
      condition     = self.publicly_accessible == false
      error_message = "Database must not be publicly accessible"
    }

    postcondition {
      condition     = self.storage_encrypted == true
      error_message = "Database storage must be encrypted"
    }
  }
}

Preconditions on Data Sources

data "aws_ami" "app" {
  most_recent = true
  owners      = ["self"]
  filter {
    name   = "name"
    values = ["app-*"]
  }

  lifecycle {
    postcondition {
      condition     = self.image_id != ""
      error_message = "No AMI found matching filter"
    }
  }
}

What’s Next?

Practice meta-argument patterns.

← replace_triggered_by Practice Exercises →

Updated: