4.5.1. Custom Conditions and Checks
💡 First Principle: Custom conditions let you encode your assumptions directly in configuration so Terraform fails fast with a clear message instead of letting a bad value cause a confusing provider error later — moving the failure earlier and making it self-explanatory.
004 expects familiarity with four mechanisms, distinguished by scope and timing:
| Mechanism | Where it lives | When it checks | Blocks apply? |
|---|---|---|---|
Variable validation | Inside a variable block | When the variable's value is set | Yes |
precondition | lifecycle block (resource/data/output) | Before the object's action | Yes |
postcondition | lifecycle block (resource/data) | After the object is read/created | Yes |
check block | Top-level check block | During plan/apply, continuously | No (warns only) |
Variable validation enforces input rules (condition + error_message). Pre/postconditions guard a resource's assumptions and guarantees — e.g., a precondition that an AMI is in the right region, a postcondition that an instance got a public IP. Check blocks are different: they assert ongoing health (optionally using scoped data sources) and report problems as warnings without failing the run, which makes them ideal for monitoring assumptions rather than gating changes.
⚠️ Exam Trap: The standout distinction: a failing check produces a warning and does not stop the apply, while a failing validation, precondition, or postcondition errors and halts. If a question asks which custom condition reports issues without blocking, the answer is the check block.
Reflection Question: Why would you use a check block (non-blocking) rather than a postcondition (blocking) to assert that a web endpoint returns HTTP 200?