What are `precondition` and `postcondition` custom conditions, and how do they differ from variable validation?
Quick Answer
precondition/postcondition blocks (nested inside a resource's, data source's, or output's lifecycle/definition) assert conditions at a different point than variable validation: a precondition checks an assumption before a resource is evaluated (e.g., "this AMI must be tagged as approved"), and a postcondition checks the result after (e.g., "the resulting EC2 instance must actually be in the expected availability zone"). Unlike variable validation, which only ever sees the raw input variable, these can reference other resources' computed attributes, values only known after planning/applying, making them suited to cross-resource invariants rather than simple input shape-checking.
Detailed Answer
Variable validation blocks (the previous question) only ever see the raw variable a caller passed in. They can't reason about anything computed later, like another resource's attributes. precondition/postcondition fill that gap.
Precondition — checking an assumption before evaluating a resource
data "aws_ami" "app" {
most_recent = true
owners = ["self"]
filter {
name = "tag:approved"
values = ["true"]
}
lifecycle {
postcondition {
condition = self.tags["approved"] == "true"
error_message = "Selected AMI is not tagged as approved for use."
}
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.app.id
lifecycle {
precondition {
condition = data.aws_ami.app.architecture == "x86_64"
error_message = "Selected AMI must be x86_64; got ${data.aws_ami.app.architecture}."
}
}
}
A precondition on aws_instance.web runs before Terraform attempts to create/update it, checking an assumption about something it depends on (here, the AMI's architecture). It catches a mismatch before any API call is made, with a message pointing at exactly what's wrong.
Postcondition — checking the result after
A postcondition (shown above on the data source) runs after the resource/data source is evaluated, asserting something about the actual resulting values. It's useful for confirming a data source actually returned what you expected (e.g., "the AMI it found really is tagged approved," catching a filter that's too loose).
Key difference from variable validation
Variable validation | precondition/postcondition | |
|---|---|---|
| Scope | The variable's own raw value only | Any expression, including other resources' computed attributes |
| Timing | Immediately, at variable assignment | Before (precondition) or after (postcondition) the specific resource/data source/output is evaluated |
| Typical use | "Is this input shaped correctly?" | "Does this cross-resource assumption/invariant actually hold?" |
Interview-ready summary
Variable validation guards the inputs to a module. precondition/postcondition guard invariants between resources that can only be checked once real values (potentially only known after planning) are available. Both exist to surface a broken assumption as an early, clear error instead of a confusing downstream failure or, worse, a successful apply that silently violates an assumption the configuration depended on.