Explains slow plans, odd ordering, "known after apply" cascades and cycle errors.
Terraform builds a directed acyclic graph from your configuration: nodes for resources, data sources, providers, variables, locals, outputs and modules; edges from references and depends_on. terraform graph prints it in DOT format.
Execution walks the graph concurrently: any node whose dependencies are done can run, up to -parallelism=10 operations at a time by default. Lower it when an API rate-limits you; raise it for large flat states.
Order details:
- Destroys run in the reverse of creation order.
- With
create_before_destroy, the replacement is created before the old object (and everything depending on it) is destroyed; the setting propagates to dependencies to keep the graph acyclic. - A cycle error means two objects depend on each other through references; break it by splitting a resource (e.g. separate security group rule resources instead of inline rules).
Unknown values: attributes computed by the provider during apply are unknown at plan time. They propagate: anything derived from them becomes (known after apply), which can force replacements to look broader than they are, and make count/for_each impossible to evaluate ("value depends on resource attributes that cannot be determined until apply"). Fix by keying on known inputs, or splitting into two applies with -target as a last resort.
Plan time grows with the number of resources and the API calls refresh makes; splitting large states is the main cure.
Example
terraform graph -type=plan | dot -Tsvg > graph.svg # needs graphviz
terraform apply -parallelism=4 # gentler on rate-limited APIs
# Classic unknown-value error:
# Error: Invalid for_each argument
# The "for_each" map includes keys derived from resource attributes
# that cannot be determined until apply...
# Fix: key on input values (names), not on IDs created in the same run.
# Cycle example message:
# Error: Cycle: aws_security_group.a, aws_security_group.b
# Fix: move the cross-references into separate aws_vpc_security_group_ingress_rule resources.Remember
- References and depends_on form a DAG walked in parallel (default 10)
- Unknown values propagate and can block count/for_each
- Cycles are fixed by splitting resources
Watch out for
- Keying for_each on IDs of resources created in the same apply.