Graph Data Structure
Terraform’s graph implementation is ininternal/dag:
Vertices
Vertices represent operations:- Resource instances
- Providers
- Variables
- Outputs
- Module expansion nodes
Edges
Edges represent “happens after” dependencies:Graph Operations
internal/dag/graph.go
Acyclic Graph Requirements
Terraform graphs must be acyclic:Root Node
Every graph must have exactly one root:Cycle Detection
Graphs are validated for cycles:internal/dag/dag.go:229
Cycle Detection Algorithm
Terraform uses Tarjan’s strongly connected components algorithm:- Time complexity: O(V + E)
- Space complexity: O(V) for stack
- Single pass: Visits each vertex once
- Finds all cycles: Returns strongly connected components
- Size 1 = no cycle
- Size > 1 = cycle
internal/dag/tarjan.go
Transitive Reduction
Removes redundant edges while preserving reachability:- Before Reduction
- After Reduction
A→C is redundant (A→B→C and A→D→C exist).
Algorithm Implementation
- For each vertex u
- For each direct descendant v of u
- Find vertices reachable from v
- Remove direct edges from u to those vertices
internal/dag/dag.go:208
Graph Walk Algorithm
TheWalker executes vertices in parallel:
Walk Initialization
Vertex Execution
internal/dag/walk.go:332
Dependency Waiting
internal/dag/walk.go:419
Walk Flow
Topological Sort
Produces a linear ordering respecting dependencies:[C, B, D, A][C, D, B, A][D, C, B, A]
internal/dag/dag.go:299
Graph Traversal Methods
Depth-First Walk
Breadth-First Walk
Walk Implementation
internal/dag/dag.go:405
Ancestors and Descendants
Utility methods for graph queries:Ancestors(A)=Descendants(E)=
internal/dag/dag.go:33
Performance Characteristics
Time Complexity
| Operation | Complexity | Notes |
|---|---|---|
| Add vertex | O(1) | Hash map insert |
| Add edge | O(1) | Set operations |
| Remove vertex | O(E) | Remove all edges |
| Validate | O(V + E) | Tarjan’s algorithm |
| Transitive reduction | O(V(V+E)) | DFS per vertex |
| Topological sort | O(V + E) | DFS-based |
| Walk | O(V + E) | Visit each vertex/edge |
| Ancestors/Descendants | O(V + E) | DFS traversal |
Space Complexity
| Structure | Complexity | Description |
|---|---|---|
| Graph | O(V + E) | Vertices + edges |
| Walker | O(V) | Per-vertex state |
| Tarjan | O(V) | Stack + indices |
Parallelism
The walker creates:- V goroutines for vertex execution
- V goroutines for dependency waiting
- Total: 2V goroutines
- Graph dependencies (natural constraint)
- Parallelism semaphore (default: 10)
Further Reading
Dependency Resolution
How references become graph edges
Modules Runtime
Graph usage in module execution