Data sources

Terraform · Essentials · 7 min

Real configurations must refer to things they don't manage: AMIs, accounts, shared networks, DNS zones.

A data source reads information without managing anything:

data "<TYPE>" "<NAME>" { ...filters... }, referenced as data.<TYPE>.<NAME>.<ATTRIBUTE>.

Typical uses:

  • Look up the latest image: data "aws_ami" with filters.
  • Read the current account and region: data "aws_caller_identity", data "aws_region".
  • Find a shared resource owned by another team: a VPC by tag, a Route 53 zone by name.
  • Build documents: data "aws_iam_policy_document" renders IAM policy JSON from HCL blocks, with validation, instead of hand-written JSON strings.
  • Read another configuration's outputs with data "terraform_remote_state" (convenient, but it couples you to that whole state; publishing values via SSM parameters or similar is often cleaner).

Data sources are read during planning when their arguments are known; if an argument depends on something not yet created, the read is deferred to apply and dependent values show as (known after apply).

A data source that finds nothing, or more than one match where one is expected, makes the plan fail, which is a useful guard. Be careful with "latest" lookups like most_recent = true: a new AMI release changes the plan and may replace your instances. Pin, or add ignore_changes, when that matters.

Example

data "aws_caller_identity" "current" {}

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]          # Canonical
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-*"]
  }
}

data "aws_iam_policy_document" "read_logs" {
  statement {
    actions   = ["s3:GetObject"]
    resources = ["arn:aws:s3:::acme-app-logs-prod/*"]
  }
}

output "account" { value = data.aws_caller_identity.current.account_id }
output "ami"     { value = data.aws_ami.ubuntu.id }

Remember

  • data blocks read; resource blocks manage
  • Reference as data.type.name.attribute
  • "Latest" lookups change over time and can trigger replacements

Watch out for

  • Using most_recent AMI lookups for long-lived instances and getting surprise replacements.

Check yourself

  1. What does Terraform do with an object found by a data source when you run destroy?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.hashicorp.com/terraform/language/data-sources

Builds on

Unlocks

Nothing builds on this yet.