CoursesTerraformIntermediate

Data sources & dependencies

Read existing infra; order resources.

Intermediate12 min · lesson 9 of 15

Not everything you reference is something Terraform created. A data source reads existing information — an AMI ID that changes weekly, a VPC created by another team, the current AWS account ID, a secret from a secrets manager — and makes it available to your configuration without managing it. Where a resource block says “make this exist,” a data block says “look this up and give me its attributes.”

main.tf
data "aws_ami" "ubuntu" { # look up the latest Ubuntu AMI
most_recent = true
owners = ["099720109477"]
filter { name = "name", values = ["ubuntu/images/*-24.04-*"] }
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id # use the looked-up value
instance_type = "t3.micro"
}

Reading another team’s outputs

A common use is stitching separated stacks together: the network stack publishes subnet IDs as outputs, and the app stack reads them with a terraform_remote_state data source pointed at the network’s backend. This lets independently-managed states share values without hard-coding IDs — the app always gets the network’s current subnets, even after the network stack changes them.

main.tf
data "terraform_remote_state" "network" {
backend = "s3"
config = { bucket = "acme-tf-state", key = "prod/network/terraform.tfstate", region = "us-east-1" }
}
resource "aws_instance" "web" {
subnet_id = data.terraform_remote_state.network.outputs.private_subnet_ids[0]
}

Explicit dependencies

Terraform infers order from references automatically, but occasionally there is a dependency it cannot see — an IAM policy that must exist before an instance uses it, with no direct attribute reference between them. depends_on states that ordering explicitly. Reach for it only when a real hidden dependency exists; overusing depends_on serializes things that could run in parallel and slows applies.

Data sources read at plan time — mind the chicken-and-egg
A data source is resolved during plan, before apply. If it looks up something that a resource in the same apply is about to create, the lookup fails or returns stale data — the resource does not exist yet when the data source runs. Read pre-existing things with data sources; reference things you create in the same run directly by their resource attributes, which Terraform orders correctly.