Explaining Dependency handling and depends_on keyword in Terraform

This page 📝 aims to provide a high-level explanation of how Terraform handles dependencies, specifically the introduction of the depends_on meta-argument. This argument is required in situations where an explicit dependency declaration is necessary.

Pavol Kutaj
2 min readNov 2


  • When preparing for deployment, Terraform goes through a planning process.
  • As part of this process, the order of actions must be determined.
  • To facilitate this:
  1. Load local state (files) data into memory.
  2. Refresh the attributes of resources and data sources from the remote environment.
  3. Parse local config (files).
  4. Construct a dependency graph based on the data sources and resources defined in the code.
  5. Perform a diff, generating a list of additions, updates, and deletions.
  • Terraform, ideally, seeks to execute changes in parallel.
  • Therefore, it works out which changes are dependent on others.
  • Changes that are not dependent on others are executed in parallel.
  • Other changes are done one after the other, in a serial fashion.

The dependency graph is based on references in configuration files

  • In the VPC resource, there is no reference:
resource "aws_vpc" "app" {
cidr_block = var.vpc_cidr_block
enable_dns_hostnames = true
tags = local.common_tags
  • However, in the subnet resource aws_subnet.public_subnet1, there is a dependency on the value of aws_vpc.app.id:
resource "aws_subnet" "public_subnet1" {
cidr_block = var.vpc_public_subnets[0]
vpc_id = aws_vpc.app.id
map_public_ip_on_launch = var.map_public_ip_on_launch
availability_zone = data.aws_availability_zones.available.names[0]
tags = local.common_tags
  • Consequently, Terraform will wait until the VPC is created before it retrieves its id and creates a subnet in that VPC.
  • Then, the aws_instance has a reference to aws_subnet.public_subnet1.id and therefore it waits for the subnet to be created, etc.
  • Terraform can manage these dependencies implicitly.
  • But sometimes, the dependency is non-obvious and Terraform needs to be explicitly informed about it.

Non-obvious/explicit dependencies are managed with the depends_on meta-argument

  • When creating aws_iam_role, both aws_iam_instance_profile and aws_iam_role_policy depend on it.
  • The aws_instance depends on aws_iam_instance_profile.
  • However, for the EC2 instances to access the S3 bucket, the aws_iam_role_policy needs to be created.
  • The solution is to add a meta-argument to the configuration — this is the depends_on keyword.
  • A meta-argument is an argument in a configuration file that instructs Terraform on how to manage the object but is not used by the provider to configure the target object.
  • The depends_on meta-argument expects a <list> of other resources/data sources that the resource depends on.
aws_instance depends_on aws_iam_role_policy
  • In the following code, the depends_on meta-argument contains a single item in a <list>:
resource "aws_instance" "nginx1" {
ami = nonsensitive(data.aws_ssm_parameter.amzn2_linux.value)
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet1.id
vpc_security_group_ids = [aws_security_group.alb_sg.id]
iam_instance_profile = aws_iam_instance_profile.nginx_profile.name
depends_on = [aws_iam_role_policy.allow_s3_all]
tags = local.common_tags

user_data = <<EOF
#! /bin/bash
sudo amazon-linux-extras install -y nginx1
sudo service nginx start
sudo rm /usr/share/nginx/html/index.html
echo '<html><head><title>Hello World</title></head><body>Hello World;</span></span></p></body></html>' | sudo tee /usr/share/nginx/html/index.html



Pavol Kutaj

Today I Learnt | Infrastructure Support Engineer at snowplow.io with a passion for cloud infrastructure/terraform/python/docs. More at https://pavol.kutaj.com