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/how/tf-dependency-graph

how/workflow

Dependency graph: what Terraform runs in parallel and what it blocks

How Terraform learns the order to create resources in. The graph built from implicit refs, parallel "layers", and why destroy runs in exactly the reverse direction.

When you write:

hcl
resource "aws_s3_bucket" "demo" {
  bucket = "linuxlab-${random_id.suffix.hex}"
}

you implicitly told Terraform that aws_s3_bucket.demo depends on random_id.suffix. Not because you said so directly, but because the bucket name holds a reference to an attribute of another resource. That is an implicit reference.

Terraform reads all such references, builds a directed acyclic graph (DAG) from them, and decides on its own what to create first, what next, and what in parallel. Press ▶ and see what this looks like on five resources.

step 1/6·00 · five resources in HCL
random_id.suffixIDLEaws_iam_role.lambdaIDLEaws_s3_bucket.demoIDLEaws_iam_policy.accessIDLEaws_..._policy_attachment.xIDLEMAIN.TFresource "random_id" "suffix" { byte_length = 4 }resource "aws_iam_role" "lambda" { ... }resource "aws_s3_bucket" "demo" { bucket = "linuxlab-${random_id.suffix.hex}"}resource "aws_iam_policy" "access" { role = aws_iam_role.lambda.id ... }resource "aws_iam_role_policy_attachment" "x" { role = aws_iam_role.lambda.name policy_arn = aws_iam_policy.access.arn}5 ресурсов в HCL · граф ещё не построен

§ steps

  1. A teaching example: a bucket that depends on random_id (for a unique name), an IAM role, an IAM policy (attached to the role), an attachment (needs both the role and the policy).

    In HCL the dependencies are not written explicitly. Terraform will see them on its own at the moment of the next command.

recap

What to remember:

  • Dependencies are computed from the code. Any reference A.B.C in the values of resource X automatically creates an edge A → X.
  • If a dependency exists but is not visible in the code (for example, an IAM role must exist before Lambda tries to assume it, and Lambda never mentions that role in HCL), you write tf-depends-on explicitly. This is a rare case, not the first option.
  • Within a single graph layer Terraform creates resources in parallel (up to 10 at a time by default, flag -parallelism=N). That is why large configs are faster than they seem.
  • On destroy the graph reverses: leaves (nothing depends on them) are deleted first, roots (others depend on them) come last.
  • A cycle in the graph means Error: Cycle. Terraform refuses to work until you untangle it (usually through refactoring or a null_resource with break-the-cycle logic). See tf-dag-internals.

Next: tf-module-io-flow on how the graph crosses module boundaries.

§ dig into the knowledge base

  • tf-dag-internalsDAG internals: how Terraform builds the graph
  • tf-depends-ondepends_on: an explicit dependency without a reference
  • tf-graphterraform graph: visualization in Graphviz
  • tf-referencesReferences between resources

§ try it hands-on

  • ›tf-beginner-09-lifecycle- Lifecycle: depends_on, create_before_destroy
  • ›tf-garden-01-cycle-error- Broken garden: a cycle in the graph
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies