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) — catching 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 — 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.