Bird
Raised Fist0
Terraformcloud~7 mins

Preconditions and postconditions in Terraform - Commands & Configuration

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Sometimes you want to check conditions before or after creating resources in Terraform. Preconditions stop the process if requirements are not met. Postconditions verify the result after creation to ensure correctness.
When you want to ensure a variable has a valid value before creating resources
When you need to check that a resource attribute meets a condition after deployment
When you want to prevent Terraform from applying changes if certain rules are broken
When you want to validate outputs to catch mistakes early
When you want to enforce policies in your infrastructure code
Config File - main.tf
main.tf
terraform {
  required_version = ">= 1.2.0"
}

variable "instance_count" {
  type    = number
  default = 2

  validation {
    condition     = var.instance_count > 0 && var.instance_count <= 5
    error_message = "instance_count must be between 1 and 5"
  }
}

resource "null_resource" "example" {
  count = var.instance_count
}

resource "null_resource" "post_check" {
  depends_on = [null_resource.example]

  lifecycle {
    ignore_changes = ["triggers"]
  }

  triggers = {
    always_run = timestamp()
  }

  provisioner "local-exec" {
    command = "echo 'Postcondition check: instance_count is ${var.instance_count}'"
  }

  # Postcondition example using a custom condition
  provisioner "local-exec" {
    when    = "destroy"
    command = "echo 'Resource is being destroyed'"
  }
}

output "instance_count_output" {
  value = var.instance_count

  # Postcondition to check output value
  postcondition {
    condition     = var.instance_count > 0
    error_message = "Output instance_count must be positive"
  }
}

terraform block: sets the minimum Terraform version to 1.2.0 which supports pre/postconditions.

variable block: defines a variable with a validation condition as a precondition to ensure the value is between 1 and 5.

null_resource example: creates dummy resources based on the variable count.

postcondition example: uses provisioners and output postcondition to check values after resource creation.

Commands
Initializes the Terraform working directory and downloads required providers.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/null... - Installing hashicorp/null v3.1.0... - Installed hashicorp/null v3.1.0 (signed by HashiCorp) Terraform has been successfully initialized!
Checks the configuration files for syntax errors and validates preconditions like variable validations.
Terminal
terraform validate
Expected OutputExpected
Success! The configuration is valid.
Applies the configuration to create resources. It will stop if preconditions fail and show errors. Postconditions run after creation.
Terminal
terraform apply -auto-approve
Expected OutputExpected
null_resource.example[0]: Creating... null_resource.example[1]: Creating... null_resource.example[0]: Creation complete after 0s [id=123456] null_resource.example[1]: Creation complete after 0s [id=123457] null_resource.post_check: Creating... null_resource.post_check: Provisioning with 'local-exec'... Postcondition check: instance_count is 2 null_resource.post_check: Creation complete after 0s [id=123458] Apply complete! Resources: 3 added, 0 changed, 0 destroyed. Outputs: instance_count_output = 2
-auto-approve - Skips interactive approval prompt
Displays the output value and verifies the postcondition on output.
Terminal
terraform output instance_count_output
Expected OutputExpected
2
Key Concept

If you remember nothing else from this pattern, remember: preconditions stop bad inputs before changes, postconditions verify results after changes.

Common Mistakes
Not setting the required Terraform version to 1.2.0 or higher
Preconditions and postconditions require Terraform 1.2.0 or newer to work properly
Specify 'required_version = ">= 1.2.0"' in the terraform block
Using invalid conditions in variable validation or output condition blocks
Terraform will fail validation or apply with unclear errors if conditions are not boolean expressions
Write clear boolean expressions for conditions, e.g., var.instance_count > 0
Expecting postconditions to prevent resource creation
Postconditions run after resource creation and only validate results; they do not stop creation
Use preconditions (variable validation) to prevent bad inputs before creation
Summary
Use variable validation blocks as preconditions to check inputs before resource creation.
Use output postcondition blocks and provisioners as postconditions to verify resource states after creation.
Run 'terraform validate' to check preconditions and 'terraform apply' to create resources and run postconditions.

Practice

(1/5)
1. What is the main purpose of precondition blocks in Terraform?
easy
A. To check conditions before applying changes
B. To verify outputs after deployment
C. To define resource dependencies
D. To configure provider settings

Solution

  1. Step 1: Understand preconditions role

    Preconditions are rules that Terraform checks before making any changes to infrastructure.
  2. Step 2: Differentiate from postconditions

    Postconditions check after changes, but preconditions ensure safety before changes.
  3. Final Answer:

    To check conditions before applying changes -> Option A
  4. Quick Check:

    Preconditions = Before changes check [OK]
Hint: Preconditions run before changes to avoid errors [OK]
Common Mistakes:
  • Confusing preconditions with postconditions
  • Thinking preconditions run after deployment
  • Assuming preconditions configure providers
2. Which of the following is the correct syntax to define a postcondition in a Terraform resource?
easy
A. postcondition { condition = var.enabled error_message = "Must be enabled" }
B. postconditions { condition = var.enabled == true error_message = "Must be enabled" }
C. postcondition { condition = var.enabled == true error_message = "Must be enabled" }
D. postcondtion { condition = var.enabled == true error_message = "Must be enabled" }

Solution

  1. Step 1: Recall correct block name and syntax

    The block is singular postcondition with a condition attribute.
  2. Step 2: Check condition expression format

    Using var.enabled == true is explicit and correct for boolean check.
  3. Final Answer:

    postcondition { condition = var.enabled == true error_message = "Must be enabled" } -> Option C
  4. Quick Check:

    Correct syntax uses singular postcondition and explicit condition [OK]
Hint: Use singular 'postcondition' with condition attribute [OK]
Common Mistakes:
  • Using plural 'postconditions' block
  • Omitting '== true' for boolean checks
  • Misspelling 'postcondition'
3. Given this Terraform snippet inside a resource:
precondition {
  condition     = var.size > 0
  error_message = "Size must be positive"
}
postcondition {
  condition     = length(self.id) > 0
  error_message = "Resource ID must be set"
}

What happens if var.size is 0 during apply?
medium
A. Terraform applies changes but shows a warning
B. Terraform stops and shows "Size must be positive" error
C. Terraform applies changes and postcondition fails silently
D. Terraform ignores precondition and applies changes

Solution

  1. Step 1: Understand precondition behavior

    Preconditions run before applying changes and block apply if false.
  2. Step 2: Evaluate condition with var.size = 0

    Condition var.size > 0 is false, so Terraform stops with error message.
  3. Final Answer:

    Terraform stops and shows "Size must be positive" error -> Option B
  4. Quick Check:

    Precondition false stops apply with error [OK]
Hint: Precondition false stops apply with error message [OK]
Common Mistakes:
  • Thinking preconditions only warn, not stop
  • Confusing precondition with postcondition timing
  • Assuming apply continues despite precondition failure
4. You wrote this postcondition in a Terraform resource:
postcondition {
  condition     = self.name != ""
  error_message = "Name must not be empty"
}

But Terraform never shows the error even if name is empty. What is the likely problem?
medium
A. Postconditions run after apply, but self.name is not set yet
B. The condition should use length(self.name) > 0 instead of self.name != ""
C. The postcondition block is misspelled and ignored
D. Postconditions run before resource creation, so condition is not checked properly

Solution

  1. Step 1: Understand postcondition timing

    Postconditions run after resource creation to verify results.
  2. Step 2: Analyze condition evaluation

    If self.name is null (not set) rather than empty string after apply, self.name != "" is true because null != "", so no error is triggered.
  3. Final Answer:

    Postconditions run after apply, but self.name is not set yet -> Option A
  4. Quick Check:

    null != "" passes; check availability [OK]
Hint: Postconditions check after apply; ensure attribute is set [OK]
Common Mistakes:
  • Assuming postconditions run before apply
  • Using wrong condition syntax without checking attribute availability
  • Misspelling postcondition block name
5. You want to ensure a Terraform resource only applies if var.region is either "us-east-1" or "us-west-2", and after apply, the resource's status attribute must be "active". Which is the correct way to write preconditions and postconditions?
hard
A.
precondition {
  condition     = var.region == "us-east-1" && var.region == "us-west-2"
  error_message = "Region must be us-east-1 and us-west-2"
}
postcondition {
  condition     = self.status != "active"
  error_message = "Status must not be active"
}
B.
precondition {
  condition     = var.region == "us-east-1" || var.region == "us-west-2"
  error_message = "Region must be us-east-1 or us-west-2"
}
postcondition {
  condition     = self.status != "active"
  error_message = "Status must not be active"
}
C.
precondition {
  condition     = var.region != "us-east-1" && var.region != "us-west-2"
  error_message = "Region must not be us-east-1 or us-west-2"
}
postcondition {
  condition     = self.status == "active"
  error_message = "Status must be active"
}
D.
precondition {
  condition     = var.region == "us-east-1" || var.region == "us-west-2"
  error_message = "Region must be us-east-1 or us-west-2"
}
postcondition {
  condition     = self.status == "active"
  error_message = "Status must be active"
}

Solution

  1. Step 1: Write correct precondition for region

    Use logical OR (||) to allow either region, with proper error message.
  2. Step 2: Write correct postcondition for status

    Check that self.status equals "active" after apply, with matching error message.
  3. Final Answer:

    Precondition uses OR for region check; postcondition checks status equals "active" -> Option D
  4. Quick Check:

    Precondition OR and postcondition equality check [OK]
Hint: Use OR for precondition, equality for postcondition [OK]
Common Mistakes:
  • Using AND instead of OR in precondition
  • Checking for inequality in postcondition wrongly
  • Mixing error messages with wrong logic