Terraform

How to Use Terraform depends_on Meta-Argument

terraform depends_on

In this article, you will learn why and how to use Terraform’s depends_on meta-argument.

Resource Dependencies in Terraform

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.

What is Terraform depends_on

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.

When to Use Terraform depends_on

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.

Terraform depends_on Example Use Cases

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 Best Practices

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.

Key Points

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 will be 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 will expand on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6. OpenTofu retained all the features and functionalities that had made Terraform popular among developers while also introducing improvements and enhancements. OpenTofu works with your existing Terraform state file, so you won’t have any issues when you are migrating to it.

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.

Start free trial
Terraform CLI Commands Cheatsheet

Initialize/ plan/ apply your IaC, manage modules, state, and more.

Share your data and download the cheatsheet