In this article, you will learn why and how to use Terraform’s depends_on
meta-argument.
Terraform uses resource dependencies to create and destroy resources in the correct order. Expression references create implicit dependencies between one resource and another resource.
The following shows an implicit dependency created between two Azure resources using an expression reference.
resource "azurerm_resource_group" "rg" {
name = "rg-example-centralus"
location = "centralus"
}
resource "azurerm_virtual_network" "vnet" {
name = "vnet-example-centralus"
resource_group_name = azurerm_resource_group.rg.name
}
In this example, an implicit dependency is created because the VNet’s resource_group_name
attribute references the name of the resource group.
The object with the dependency, the VNet, is referred to as the “object declaring the dependency.” The resource group is referred to as the “dependency object.”
Terraform completes all actions on the dependency object first, then performs actions on the object declaring the dependency.
In most scenarios, Terraform automatically determines dependencies between resources based on expressions within a resource block.
There are rare scenarios, however, where Terraform cannot infer dependencies between resources. In these cases, you will need to create an explicit dependency. This is the purpose of the Terraform depends_on
meta-argument.
Terraform depends_on
allows you to create an explicit dependency between two resources.
Dependencies are not limited to just resources. They can be created between modules. When the dependency is a module, depends_on
affects the order in which Terraform processes all the resources and data sources associated with that module.
Both implicit and explicit dependencies affect the order in which resources are destroyed as well as created. Explicit dependencies are only necessary when a resource or module relies on another resource’s behavior but does not access any of that resource’s data in its arguments.
There are some things you should consider when using Terraform depends_on
:
- Always include a comment to explain why using
depends_on
is necessary. depends_on
causes Terraform to create a more conservative plan. The plan may modify more resources than necessary. For example, there may be more values as unknown “(known after apply).” This is more likely to occur when creating explicit dependencies between modules.- Adding explicit dependencies can increase the length of time it takes to build your infrastructure. Terraform must wait until the dependency object is created before continuing.
- It is recommended to use expression references to create implicit dependencies whenever possible.
Terraform’s implicit dependencies mechanism is more than enough for most use cases. Usually, when you use depends_on, there is a problem with your code, rather than a need for a particular dependency. However, dependencies are required in some cases:
- Ensuring resource configuration – You may need a resource to be fully configured before starting the creation of another one that depends on it
- Terraform provisioners – If you are using Terraform null resources and Terraform data in conjunction with a provisioner, you will need to ensure that an instance is created before you can run a script on it
- Enforcing creation order – If there are resources in your configuration that must be created in a particular order, you can use depends_on to enforce it
- Workarounds – Terraform may have limitations that can only be addressed by using the depends_on block.
Some scenarios that may require the use of an explicit dependency include running a SQL script after a DB is created, deploying containers only after the container registry is created, or you have an application running on a VM instance that expects to use a specific Azure Storage Container.
This dependency is not visible to Terraform since the application’s architecture controls it. The following snippet demonstrates an explicit dependency between a VM and a storage container.
resource "azurerm_windows_virtual_machine" "vm" {
resource_group_name = "rg-demo"
name = "vm-demo"
location = "centralus"
size = "Standard_F2"
admin_username = "adminuser"
admin_password = "P@$$w0rd1234!"
network_interface_ids = [
azurerm_network_interface.nic.id,
]
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
# all other relevant attributes
depends_on = [
azurerm_storage_account.st
]
}
resource "azurerm_storage_account" "st" {
resource_group_name = "rg-demo"
name = "stdemo"
location = "centralus"
account_tier = "Standard"
account_replication_type = "LRS"
# all other relevant attributes
}
Adding Multiple Dependency Objects
Multiple dependencies can be passed to the depends_on
argument using a comma-separated list of resources.
Note: Adding explicit dependencies can increase the length of time it takes to create your infrastructure because Terraform will wait to create the dependent resource until after the specified resource is created.
The following snippet expands on the example from above and adds a second dependency, an Azure SQL Server, to the VM. This example is for illustration purposes and does not represent the best use case for creating an explicit dependency to multiple resources.
resource "azurerm_windows_virtual_machine" "vm" {
# all other relevant attributes
depends_on = [
azurerm_storage_account.st,
azurerm_mssql_server.sql
]
}
resource "azurerm_mssql_server" "sql" {
resource_group_name = "rg-demo"
name = "stdemo"
location = "centralus"
administrator_login = "adminuser"
administrator_login_password = "P@$$w0rd1234!"
version = "12.0"
# all other relevant attributes
}
How to use depends_on
for modules in Terraform
As mentioned above, resources can have explicit dependencies on modules and vice-versa. This next example uses a module from the Terraform registry to create a VM. The module will be dependent upon the successful creation of the storage account.
module "virtual-machine" {
source = "Azure/network/azurerm"
resource_group_name = "rg-demo"
# all other relevant attributes
depends_on = [
azurerm_storage_account.st
]
}
resource "azurerm_storage_account" "st" {
# all other relevant attributes
}
Here’s an example of the same two resources with the dependency reversed. In this example, the storage account resource is dependent upon the VM module. Note the use of the module
keyword in the dependency resource.
module "virtual-machine" {
source = "Azure/network/azurerm"
resource_group_name = "rg-demo"
# all other relevant attributes
}
resource "azurerm_storage_account" "st" {
# all other relevant attributes
depends_on = [module.virtual-machine]
}
Terraform depends_on can be helpful in some situations, but you need to follow best practices when leveraging it:
- Limit usage – Overuse of depends_on can lead to complex code that is difficult to troubleshoot.
- Test your dependencies – Catch any potential issues early, to reduce the risk of problems during actual infrastructure provisioning.
- Be specific – Avoid broad dependencies if you can use a specific one.
- Try to use it only for workarounds – Use it for temporary workarounds for limitations or bugs in Terraform providers.
Document the reasoning behind using it – Specify if it is a workaround, you are ensuring resource configuration, or any other use case you may have. This will help the team understand the reason for using it.
Understanding how Terraform uses implicit and explicit dependencies helps you to determine when and how to use the depends_on
meta-argument. When necessary, depends_on
instructs Terraform to create and destroy resources in the correct order. Misusing the argument can lead to potentially confusing, poor-performing code.
If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box. You can check it for free by creating a trial account.
Note: New versions of Terraform are placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.
Terraform Management Made Easy
Spacelift effectively manages Terraform state, more complex workflows, supports policy as code, programmatic configuration, context sharing, drift detection, resource visualization and includes many more features.