Overview
Dependency resolution happens in two phases: Phase 1: Static Analysis- Parse configuration into AST
- Extract all references from expressions
- Validate reference syntax
- Map references to graph vertices
- Create dependency edges
- Handle special dependency cases
Reference Types
Terraform supports several reference forms:Resource References
data.aws_ami.ubuntu.id→ data resource dependencyaws_subnet.private.id→ managed resource dependencyaws_security_group.app.id→ managed resource dependencyaws_security_group.common.id→ managed resource dependency
Variable References
aws_instance.web depends on variable instance_count
Local Value References
aws_instance.app depends on local value common_tags
Module References
aws_instance.app depends on module vpc output
Self References
internal/terraform/validate_selfref.go
Reference Extraction
References are extracted from HCL expressions:Expression Analysis
HCL Traversal
References start as HCL traversals:Address Parsing
Traversals are parsed into typed addresses:internal/addrs/referenceable.go
Reference Map
TheReferenceMap connects references to vertices:
Looking Up References
- Vertex
aws_instance.appimplementsGraphNodeReferencer - Returns reference to
aws_subnet.private - Reference map looks up
"aws_subnet.private" - Returns vertex for that resource
internal/terraform/reference_map.go
ReferenceTransformer
TheReferenceTransformer creates graph edges:
- Destroy nodes ignored: They rely on state, not references
- Inter-module-instance blocked: Prevents invalid dependencies
- Edge direction: From referencer to referenced
internal/terraform/transform_reference.go:112
Special Dependency Cases
Explicit Dependencies (depends_on)
Manual dependency declaration:Data Resource Dependencies
Data resources have special dependency handling:internal/terraform/transform_reference.go:178
Module Variable Dependencies
Module input variables are resolved in parent scope:ReferenceOutside:
internal/terraform/transform_module_variable.go
Provider Dependencies
Resources automatically depend on their providers:internal/terraform/transform_provider.go:39
Provisioner Dependencies
Provisioners depend on connections:- Provisioner depends on resource (implicit)
- Provisioner depends on
aws_s3_bucket.assets(from inline reference)
internal/terraform/transform_provisioner.go
Dependency Graph Example
Given this configuration:var.regionprovider.awsdata.aws_ami.ubuntuandaws_vpc.main(parallel)aws_subnet.privateaws_instance.app
Reference Resolution Errors
Undefined Reference
Self-Reference in Count
internal/terraform/validate_selfref.go
Cycle Detection
Cross-Module Instance Reference
module.servers (all instances), not module.servers[0] (specific instance).
Performance Considerations
Reference Extraction
Complexity: O(E) where E is number of expressions- Each expression analyzed once
- Traversal parsing is O(1) per reference
- No deep analysis required
Reference Map Construction
Complexity: O(V * R) where:- V = number of vertices
- R = average referenceable addresses per vertex
Reference Resolution
Complexity: O(V * D) where:- V = number of vertices
- D = average dependencies per vertex
Optimization: Caching
Reference map caches address-to-vertex lookups:Integration with Graph Builders
Reference transformer is used in all graph builders:- Must run after vertex creation transforms
- Must run before transitive reduction
- Typically near end of transform pipeline
internal/terraform/graph_builder_plan.go
Reference Scope and Namespacing
References are scoped to modules:- Each module has its own namespace
- Resources reference within same module
- Cross-module via module outputs
- Variables connect modules
Further Reading
Graph Evaluation
How dependency graphs are executed
Modules Runtime
Complete graph building pipeline