Terraform Depends On and Resource Dependencies

Infrastructure components often depend on each other. A web server cannot join a network that does not exist yet. A database cannot receive connections before its security group is configured. Terraform manages this through dependencies — both automatic and explicit. This topic explains how Terraform determines order and when you need to step in manually.

Why Order Matters

Cloud resources are not created in the order they appear in your files. Terraform builds a dependency graph and creates resources in parallel where possible — but it always respects dependencies to avoid errors.

Diagram: Deployment Order from Dependencies

What you want to create:
  VPC → Subnet → Security Group → EC2 Instance → Elastic IP

Terraform dependency graph:
  aws_vpc.main
       |
       v
  aws_subnet.app -----> aws_security_group.web
                               |
                               v
                        aws_instance.server
                               |
                               v
                        aws_eip.server_ip

Terraform creates from top to bottom,
parallelising where branches allow.

Implicit Dependencies

When you reference one resource's attribute inside another resource, Terraform automatically detects the dependency. No extra code needed.

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "app" {
  vpc_id     = aws_vpc.main.id    # <-- implicit dependency
  cidr_block = "10.0.1.0/24"
}

Terraform sees that aws_subnet.app references aws_vpc.main.id. It creates the VPC first, then the subnet. You did not write any special ordering code — the reference itself declares the dependency.

Implicit dependencies cover the vast majority of real-world cases. Most of the time, you never need to think about order at all — it happens automatically from your attribute references.

Explicit Dependencies with depends_on

Sometimes one resource logically depends on another, but does not reference any of its attributes. Terraform cannot detect this dependency automatically. The depends_on meta-argument handles this case.

When Implicit Dependencies Are Not Enough

Imagine you create an IAM role and an S3 bucket. You then create an EC2 instance that will use that IAM role to read from that bucket. The instance references the role, so Terraform creates the role first. But the IAM policy attached to the role might not have propagated yet when the instance starts — IAM changes take a few seconds to become consistent across AWS.

resource "aws_iam_role" "app_role" {
  name = "app-ec2-role"
  # ... role configuration
}

resource "aws_iam_role_policy_attachment" "app_policy" {
  role       = aws_iam_role.app_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}

resource "aws_instance" "app" {
  ami                  = data.aws_ami.linux.id
  instance_type        = "t3.micro"
  iam_instance_profile = aws_iam_instance_profile.app.name

  depends_on = [aws_iam_role_policy_attachment.app_policy]
  # Terraform waits for the policy attachment to complete
  # before creating this instance
}

The instance already references aws_iam_instance_profile.app (implicit dependency on the profile). The depends_on adds an additional dependency on the policy attachment — ensuring the policy is attached before the instance starts, even though no attribute is directly referenced.

depends_on Syntax

resource "RESOURCE_TYPE" "NAME" {
  # ... arguments

  depends_on = [
    resource_type.resource_name,
    another_resource_type.another_name
  ]
}

depends_on accepts a list of resource references. It also works on modules:

module "app" {
  source = "./modules/application"

  depends_on = [module.networking]
}

Visualising Your Dependency Graph

Terraform can export its dependency graph in DOT format — a standard graph description language that graphing tools can render as a visual diagram.

terraform graph | dot -Tsvg > graph.svg

This command requires the graphviz tool installed separately. The resulting SVG shows every resource as a node and every dependency as a directed arrow — invaluable for understanding complex configurations.

Resource Creation and Destruction Order

Dependencies affect both creation and destruction order — but in opposite directions.

OperationOrder
CreateDependencies first, then dependents
DestroyDependents first, then dependencies

If you destroy a stack, Terraform deletes the EC2 instance before the subnet, deletes the subnet before the VPC, and so on — always working backwards up the dependency chain.

Common Mistakes with Dependencies

  • Circular dependencies: Resource A depends on B, and B depends on A. Terraform detects this and throws an error. Resolve by refactoring — often by extracting a shared resource that both A and B reference.
  • Overusing depends_on: Adding depends_on where an attribute reference already handles the dependency causes slower plans and unnecessary serialisation. Rely on implicit dependencies whenever possible.

Key Points

  • Terraform builds a dependency graph and creates resources in dependency order — not file order.
  • Implicit dependencies form automatically when you reference one resource's attribute inside another resource block.
  • Use depends_on only when a dependency exists that Terraform cannot detect from attribute references alone.
  • Destruction order is the reverse of creation order — dependents are destroyed before their dependencies.
  • Use terraform graph to visualise the dependency graph of a complex configuration.

Leave a Comment