Terraform configuration
Language surface
HCL provides variable blocks (type, default, description, validation, sensitive, nullable), locals, output, expressions (conditionals, for expressions, splats, string templates) and built-in functions such as lookup, merge, cidrsubnet, try, can and coalesce.
Meta-arguments
count (integer), for_each (map or set of strings), depends_on, provider, and lifecycle { create_before_destroy, prevent_destroy, ignore_changes, replace_triggered_by }.
Traps that show up repeatedly
for_eachcannot take a list - convert withtoset()or reshape into a map.count.indexyields numeric addresses (aws_instance.web[0]). Deleting an item from the middle of a list shifts every later index and causes needless churn; usefor_eachfor stable addressing.depends_ontakes a static list of references, not arbitrary expressions over resource attributes.sensitive = trueonly masks CLI output; the value is still stored in plaintext in state.- Provisioners (
local-exec,remote-exec) are a last resort; prefer provider-native features orterraform_datawith triggers. - Variable precedence, lowest to highest: defaults →
TF_VAR_environment →terraform.tfvars→*.auto.tfvars(alphabetical) →-var/-var-fileon the CLI (last flag wins). ignore_changes = [tags["Owner"]]uses attribute paths and acceptsall.
Rule of thumb
Ask whether the set of instances is identified by keys (use for_each) or is simply N identical copies (use count).