2.07 - Terraform Resource Attributes & Reference Expressions
Overview
Resource attributes allow you to link resources together by using the output of one resource as the input of another, enabling Terraform to model real infrastructure dependencies.
Abstract
In real-world infrastructure, resources rarely exist in isolation. Terraform's reference expressions let you pass attributes from one resource directly into another, creating implicit dependencies and dynamic configurations that reflect actual infrastructure relationships.
Key Concepts
| Concept | Description |
|---|---|
| Resource attribute | A value exported by a resource after it is created (e.g. id, arn, ip) |
| Attribute reference | An expression that reads an attribute from another resource |
| Interpolation sequence | ${...} syntax used to embed an expression inside a string |
| Implicit dependency | Terraform infers creation order automatically from reference expressions |
| Explicit dependency | Dependency declared manually using depends_on when no reference expression is used |
depends_on |
Meta-argument that accepts a list of resources the current resource must wait for |
id attribute |
Most resources expose an id attribute representing their unique identifier |
Reference Expression Syntax
To use an attribute from another resource:
Inside a string argument, wrap it in an interpolation sequence:
| Part | Example |
|---|---|
| Resource type | random_pet |
| Resource name | my-pet |
| Attribute | id |
Example Configuration
Without reference (no dependency)
resource "local_file" "pet" {
filename = var.filename
content = "My favorite pet is Mr.Cat"
}
resource "random_pet" "my-pet" {
prefix = var.prefix
separator = var.separator
length = var.length
}
The file content is hardcoded — no relationship between the two resources.
With reference expression (linked resources)
resource "local_file" "pet" {
filename = var.filename
content = "My favorite pet is ${random_pet.my-pet.id}"
}
resource "random_pet" "my-pet" {
prefix = var.prefix
separator = var.separator
length = var.length
}
Now the file content is dynamically populated with the pet name generated by random_pet.my-pet.
How It Works at Apply Time
When terraform apply runs:
random_pet.my-petis created first (Terraform infers the dependency).- The
idattribute — the generated pet name (e.g.Mr.Bull) — becomes available. local_file.petis created withcontent = "My favorite pet is Mr.Bull".
random_pet.my-pet: Creating...
local_file.pet: Creating...
random_pet.my-pet: Creation complete after 0s [id=Mr.bull]
local_file.pet: Creation complete after 0s
[id=059090e865809f9b6debfda7aebf48fdce2220a6]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Resource Dependencies
Terraform supports two types of resource dependency.
Implicit Dependency
Created automatically when one resource references an attribute of another via a reference expression. Terraform builds the dependency graph from these references and determines the correct creation and destruction order without any extra configuration.
resource "local_file" "pet" {
filename = var.filename
content = "My favorite pet is ${random_pet.my-pet.id}" # reference creates implicit dependency
}
resource "random_pet" "my-pet" {
prefix = var.prefix
separator = var.separator
length = var.length
}
Creation order: random_pet.my-pet → local_file.pet
Destruction order: local_file.pet → random_pet.my-pet
Explicit Dependency (depends_on)
Used when a resource relies on another indirectly — for example, a script that reads a file created by another resource — but no reference expression is present. Use depends_on to manually declare the relationship:
resource "local_file" "pet" {
filename = var.filename
content = "My favorite pet is Mr.Cat"
depends_on = [
random_pet.my-pet
]
}
resource "random_pet" "my-pet" {
prefix = var.prefix
separator = var.separator
length = var.length
}
depends_on accepts a list of resource references and ensures the listed resources are fully created before this resource is provisioned.
Note
Prefer implicit dependencies wherever possible — they're self-documenting and easier to maintain. Use depends_on only when the dependency cannot be expressed through a reference expression.
Resource Replacement on Attribute Change
If the referenced attribute changes (e.g. random_pet generates a new name), Terraform will destroy and recreate any dependent resources whose content no longer matches:
# local_file.pet must be replaced
-/+ resource "local_file" "pet" {
~ content = "My favorite pet is Mrs.Cat!" ->
"My favorite pet is Mr.bull" # forces replacement
directory_permission = "0777"
file_permission = "0777"
filename = "/roots/pets.txt"
~ id = "98af5244e23508cffd4a0c3c46546821c4ccbbd0" -> (known after apply)
}
local_file.pet: Destroying...
local_file.pet: Destruction complete after 0s
local_file.pet: Creating...
local_file.pet: Creation complete after 0s
[id=e56101d304de7cf1b1001102923c6bdeaa60c523]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Note
When a referenced attribute changes, Terraform marks the dependent resource for replacement (-/+), destroys the old version, and creates a new one. This is expected behaviour — not an error.
Finding Available Attributes
Every resource in the Terraform Registry documents its exported attributes under the Attribute Reference section.
For random_pet:
| Attribute | Type | Description |
|---|---|---|
id |
string | The randomly generated pet name |
Always check the registry docs for the resource you're using to see which attributes are available for reference.
Best Practices
Best Practices
- Use reference expressions instead of hardcoded values to keep configurations dynamic and environment-agnostic.
- Prefer implicit dependencies (via references) over explicit
depends_on— they're self-documenting and easier to maintain. - Use
depends_ononly when a resource has an indirect dependency that cannot be expressed through a reference expression. - Use interpolation
${...}only inside strings; for non-string arguments, reference expressions can be used directly (e.g.filename = local_file.pet.id). - Check the Attribute Reference section of provider docs to know exactly which attributes are available post-apply.
Security Best Practices
Security
- Avoid referencing sensitive attributes (e.g. passwords, tokens) in
contentfields of files or outputs — they may be stored in state in plaintext. - Mark sensitive outputs and variables with
sensitive = trueto suppress them in CLI output. - Never write secrets to
local_fileresources — use a secrets manager instead.
Do and Don't
| ✅ Do | ❌ Don't |
|---|---|
Use ${resource_type.name.attribute} to link resources |
Hardcode values that another resource already generates |
| Check the Attribute Reference section in Terraform Registry docs | Guess which attributes are available — verify in the docs |
| Let Terraform infer order via implicit dependencies | Use depends_on when a reference expression already models the relationship |
Use depends_on for indirect dependencies with no reference expression |
Omit depends_on when two resources are related but share no direct attribute reference |
Expect -/+ replacement when a referenced value changes |
Assume dependent resources update in-place |
Common Mistakes
Common Mistakes
- Forgetting the
${}interpolation wrapper when embedding a reference inside a string argument. - Referencing an attribute that doesn't exist on the resource type — always verify in the registry docs.
- Assuming resources are created in the order they appear in the file — Terraform determines order from the dependency graph, not file position.
- Not accounting for resource replacement when an upstream attribute changes — plan output will show
-/+.
Quick Recap
- Resource attributes are values exported by a resource after creation (e.g.
id). - Reference syntax:
resource_type.resource_name.attribute - Use
${...}to embed references inside string values (interpolation). - References create implicit dependencies — Terraform builds the correct creation order automatically.
- Destruction always happens in reverse dependency order.
- Use
depends_onfor explicit dependencies when no reference expression exists. - If a referenced attribute changes, Terraform destroys and recreates dependent resources.
- Always check the Attribute Reference section in Terraform Registry documentation.
Interview / Revision Notes
-
Q: What is the syntax for a Terraform reference expression?
A:resource_type.resource_name.attribute— e.g.random_pet.my-pet.id -
Q: What is an interpolation sequence?
A:${...}— evaluates an expression and inserts the result as a string inside a string argument. -
Q: How does Terraform know which resource to create first when one references another?
A: It builds an implicit dependency graph from reference expressions and resolves the correct order automatically. -
Q: What is the difference between implicit and explicit dependency?
A: Implicit dependency is inferred automatically from reference expressions. Explicit dependency is declared manually usingdepends_onwhen no reference expression is present. -
Q: When should you use
depends_on?
A: Only when a resource has an indirect dependency on another — e.g. a script that uses an output file — but no attribute reference exists to model that relationship. -
Q: In what order does Terraform destroy resources with dependencies?
A: Reverse dependency order — dependents are destroyed before the resources they depend on. -
Q: Where do you find which attributes a resource exports?
A: The Attribute Reference section of the resource's page in registry.terraform.io. -
Q: What happens to a dependent resource when the attribute it references changes?
A: It is marked for replacement (-/+) — destroyed and recreated with the updated value.