Terraform normally infers ordering when one block references another block’s attributes. Use the depends_on meta-argument when a real dependency exists but no attribute link expresses it. section 2.7.3 section 2.2.5
Make a NAT gateway wait for the internet gateway
An AWS NAT gateway can require an internet gateway to exist even though it has no argument referencing that gateway. Declare the relationship explicitly:\n\nresource "aws_nat_gateway" "example" {\n subnet_id = aws_subnet.example.id\n depends_on = [aws_internet_gateway.main]\n}\n\nThis prevents Terraform from attempting to create the NAT gateway first. The same pattern applies when cloud-network resources have operational dependencies that Terraform cannot infer from configuration values. section 2.7.3
Apply depends_on with these operational distinctions:
- Use it for hidden dependencies, such as network access components that must exist before dependent resources can launch. section 5.7.3
- Attach it to a module block when every resource in that module must wait for another resource or module. section 2.7.3
- Add it to scoped data sources inside check blocks when variable-based inputs provide no implicit dependency; otherwise the check can run during the first plan. section 10.6.2
- Balance explicit ordering against system complexity: stronger dependency chains can prevent failures but make changes harder to understand and manage. section 5.7.3
Listing 2.32 An explicit dependency between two resources
resource "aws_internet_gateway" "main" { #1
vpc_id = aws_vpc.main.id
}
resource "aws_nat_gateway" "example" {
subnet_id = aws_subnet.example.id
#2
depends_on = [ #3
aws_internet_gateway.main #4
]
}
Inspect the annotated resource listing showing an explicit dependency between an internet gateway and a NAT gateway. section 2.7.3
Listing 10.33 check block with data source dependencies
check "health_check" {
data "http" "api" {
url = var.healthcheck_endpoint #1
request_headers = {
Accept = "application/json"
}
depends_on = [module.api] #2
}
assert {
condition = data.http.api.status_code >= 200 &&
data.http.api.status_code < 300
error_message = "Healthcheck failed with status code
${data.http.api.status_code} and content ${data.http.api.request_body}."
}
}
#1 Since we are using a variable there is no implicit dependency on this data source.
#2 To prevent the first run of this check from failing we need to make this block depend on the module that launches the API.
Inspect the health-check listing showing a scoped HTTP data source waiting for an API module. section 10.6.2
