linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
Intro
Lessons
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Knowledge base
  • Cheat sheet
  • Capstone
  • Interview prep
home/terraform/kb/Workflow/tf-graph

kb/workflow ── Workflow ── beginner

terraform graph: resource dependency graph

`terraform graph` prints the resource dependency directed acyclic graph (DAG) in Graphviz dot format. It shows what depends on what and why Terraform applies resources in a particular order. Use it when debugging cycle errors or understanding large projects.

view as markdownaka: terraform-graph, dependency-graph

Why the graph exists

Terraform is declarative. You write "there must be a bucket, there must be an EC2 instance whose user_data references that bucket," and Terraform works out the order: bucket first, EC2 second.

That "works it out" part happens inside a directed acyclic graph (DAG). Each resource is a node. Each reference like aws_s3_bucket.demo.arn in another resource's code is an edge pointing from consumer to source. Terraform builds this graph, finds a topological sort, and applies resources in that order.

terraform graph exposes this graph. It is a window into Terraform's internals.

Basic output

bash
cd ~/myproject
terraform graph

Stdout contains text in Graphviz dot format:

digraph {
  compound = "true"
  newrank = "true"
  subgraph "root" {
    "[root] aws_s3_bucket.demo (expand)" [label = "aws_s3_bucket.demo", shape = "box"]
    "[root] random_id.suffix (expand)" [label = "random_id.suffix", shape = "box"]
    "[root] aws_s3_bucket.demo (expand)" -> "[root] random_id.suffix (expand)"
    ...
  }
}

This text is not meant to be read directly. To view it you need to convert it to an image.

Converting to PNG/SVG

If graphviz is installed:

bash
terraform graph | dot -Tpng > graph.png
terraform graph | dot -Tsvg > graph.svg

Open the image and you will see resource boxes with arrows. An arrow from aws_s3_bucket.demo to random_id.suffix means "the bucket depends on random_id."

On Linux/macOS:

bash
sudo apt install graphviz   # Ubuntu/Debian
brew install graphviz       # macOS

On Windows: install Graphviz and add dot.exe to PATH.

Graph modes

By default terraform graph shows the plan graph (what will happen on apply). Other modes are available:

bash
terraform graph -type=plan         # default, for the upcoming apply
terraform graph -type=plan-destroy # for terraform destroy
terraform graph -type=apply        # post-apply: what has already been created

Most of the time plan is what you want. The apply type shows only nodes that were actually changed.

What to look for in the graph

1. Isolated nodes with no edges

These are resources with no dependencies. They apply first, in parallel. If you expected a resource to wait for another but there is no edge, the dependency is not declared.

Fix it by referencing an attribute (implicit dependency) or by adding depends_on = [...] (explicit). See tf-depends-on.

2. Cycles

If resource A depends on B and B depends on A, the graph is cyclic. That is not a valid DAG, and Terraform will fail:

Error: Cycle: aws_iam_role.a, aws_iam_policy.b

Cycles are visible in the graph as two edges between the same pair of nodes pointing in opposite directions. See tf-common-errors for how to resolve cycles.

3. Long chains

If 10 resources form a sequential chain (a → b → c → ...), Terraform's parallelism is lost. An apply that could take 1 minute takes 10. Sometimes this is unavoidable (RDS must exist before the EC2 instance that connects to it). Other times it is a side-effect of unnecessary depends_on entries.

Using jq for analysis

Terraform 1.4+ added terraform graph -draw-cycles to highlight cycles. For machine-readable analysis, JSON via terraform show -json is more convenient:

bash
terraform plan -out=plan.bin
terraform show -json plan.bin | jq '.resource_changes[].address'

This gives you the address of every resource that will change. From there you can build reports or feed the data into other tools.

Rover: an alternative

For interactive visualization there is Rover, which starts a local web server with a clickable graph.

bash
rover -tfPath /path/to/terraform-binary

For large projects (50+ resources) this is far more usable than a dot PNG.

Pitfalls

  • The output of terraform graph is large even for small projects. Every provider, local value, and data source is a node too. Do not be alarmed by 50 nodes for 5 resources; most of them are internal.

  • DOT format does not always render cleanly. Large projects produce spaghetti on a PNG. Alternatives: Rover (interactive), Inframap (simplified cloud graph), or terraform graph -type=plan with manual grep filtering by resource type.

  • The graph depends on the current state. If state is empty, the graph shows "add everything." If some resources already exist, only new ones appear. To see the full graph of the current project, run terraform refresh first.

  • -type=plan-destroy shows the reverse order. Destroy goes from leaves to root: dependents first, then their dependencies. Use this mode when you want to understand the teardown sequence.

  • -draw-cycles was added in TF 1.4. On older versions you must find cycles by eye in the DOT output or with grep '->'.

§ команды

bash
terraform graph

Print the dependency graph in Graphviz DOT format to stdout.

bash
terraform graph | dot -Tpng > graph.png

Save the graph as an image. Requires graphviz to be installed.

bash
terraform graph -type=plan-destroy | dot -Tpng > destroy.png

Graph for terraform destroy: shows the order in which resources will be removed.

bash
terraform graph -draw-cycles

TF 1.4+: highlight cycles in the graph. Useful when diagnosing cycle errors.

bash
terraform graph | grep '->'

List all dependency edges. Handy when you want to grep for specific resource types.

§ см. также

  • tf-depends-onResource dependencies: explicit and implicitTerraform automatically computes the creation order of resources from references in HCL (implicit dependencies). When no such reference exists but order matters, use depends_on. Use it rarely; it is usually a signal that the architecture needs reconsideration.
  • tf-referencesReferences in HCL: how to read aws_s3_bucket.demo.bucketAny value in HCL is reachable through an address: var.x, local.x, aws_s3_bucket.demo.arn, module.net.vpc_id, data.aws_region.current.name. Knowing this syntax is half of your productivity in Terraform.
  • tf-planterraform plan: see what Terraform is about to doplan is a dry run: Terraform reads your HCL, reads the state, and shows the diff between them. It changes nothing in the cloud. This is your main tool for not breaking prod by mistake.
  • tf-common-errorsCommon Terraform Errors and How to Fix ThemA catalog of the Terraform errors you will hit again and again: cycle dependencies, "value depends on resource attributes that cannot be determined until apply", state lock, inconsistent plan, "for_each argument cannot include keys derived from resource attributes". For each one, the cause and the fix.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies