Terraform is pretty good at figuring things out on its own. In most cases, it builds a dependency graph automatically and provisions resources in the correct order. But sometimes, that implicit logic just isn’t enough.
That’s where depends_on comes in.
If you’ve ever run into situations where resources are created too early—or worse, fail because something wasn’t ready yet—you’ve already felt the need for explicit dependencies.
What is Terraform depends_on?
depends_on is a meta-argument in Terraform that lets you explicitly define resource dependencies when Terraform can’t infer them automatically.
In simple terms: you’re telling Terraform, “Don’t even try to create this until that is fully done.”
Basic Syntax
1resource "aws_instance" "app" {
2 ami = "ami-123456"
3 instance_type = "t3.micro"
4
5 depends_on = [aws_security_group.app_sg]
6}Here, Terraform ensures the security group is created before launching the instance—even if there’s no direct attribute reference between them.
Wait… Doesn’t Terraform Handle Dependencies Automatically?
Yes, most of the time.
Terraform builds a dependency graph based on references. For example:
1resource "aws_instance" "app" {
2 ami = "ami-123456"
3 instance_type = "t3.micro"
4 vpc_security_group_ids = [aws_security_group.app_sg.id]
5}Here, Terraform knows the instance depends on the security group because you referenced its ID.
No depends_on needed.
So when does it fail?
When dependencies are indirect, hidden, or purely operational rather than data-driven.
Real-World Scenarios Where depends_on Matters
1. Provisioners and Side Effects
Provisioners don’t create explicit dependencies in Terraform’s graph.
1resource "null_resource" "setup" {
2 provisioner "local-exec" {
3 command = "echo Setup complete"
4 }
5}
6
7resource "aws_instance" "app" {
8 ami = "ami-123456"
9 instance_type = "t3.micro"
10}Terraform might run these in parallel, which can break assumptions.
Fix it with:
1resource "aws_instance" "app" {
2 ami = "ami-123456"
3 instance_type = "t3.micro"
4
5 depends_on = [null_resource.setup]
6}2. External Systems or APIs
Sometimes a resource relies on something outside Terraform—like a DNS propagation or external service readiness.
Example: waiting for an IAM role to fully propagate before attaching policies.
3. Modules with Hidden Dependencies
Modules can obscure relationships.
1module "network" {
2 source = "./network"
3}
4
5module "app" {
6 source = "./app"
7}If app relies on resources inside network but doesn’t explicitly reference them, Terraform won’t know the order.
Solution:
1module "app" {
2 source = "./app"
3
4 depends_on = [module.network]
5}How Terraform Uses depends_on Internally
Terraform builds a directed acyclic graph (DAG) of resources. Adding depends_on inserts additional edges into that graph.
This affects:
- Creation order
- Destruction order (reverse dependencies)
- Parallelism during apply
It doesn’t change resource configuration—it only affects execution sequencing.
A Subtle Gotcha: Overusing depends_on
A common mistake developers make is adding depends_on everywhere “just to be safe.”
This can actually hurt your infrastructure:
- Reduces parallelism → slower applies
- Makes dependency graph harder to reason about
- Hides proper design issues
If Terraform can infer a dependency through references, let it.
Bad Pattern
1depends_on = [aws_vpc.main]…when you're already referencing aws_vpc.main.id somewhere.
Redundant and unnecessary.
Cleaner Alternative: Use Data Flow First
Before reaching for depends_on, ask:
Can I express this dependency through an attribute reference?
Terraform is designed to work best when dependencies are derived from data flow rather than manual ordering.
Example
1subnet_id = aws_subnet.app.idThis is better than forcing:
1depends_on = [aws_subnet.app]Multiple Dependencies
You can specify more than one dependency:
1depends_on = [
2 aws_security_group.app_sg,
3 aws_iam_role.app_role
4]Terraform will wait for all of them before proceeding.
Applies to More Than Just Resources
depends_on works with:
- Resources
- Modules
- Data sources (in newer Terraform versions)
This makes it useful across complex infrastructure stacks.
When You Definitely Should Use depends_on
- When dealing with provisioners
- When dependencies are not expressed in attributes
- When modules hide internal resource relationships
- When timing/order matters beyond configuration
When You Should Avoid It
- When Terraform already infers dependencies
- To “fix” race conditions caused by poor design
- As a default habit in every resource
Quick Mental Model
If Terraform can see the data flow, don’t use depends_on.
If Terraform can’t see the relationship, that’s your signal to use it.
Wrapping It Up
depends_on is a precision tool, not a safety net.
Used correctly, it solves edge cases where Terraform’s dependency graph falls short. Used excessively, it slows things down and hides better solutions.
When in doubt, prefer explicit references. Reach for depends_on only when the dependency is real—but invisible to Terraform.