100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

Data Sources Explained

Learn how Terraform data sources let you read information about existing infrastructure or external systems without managing it, so configurations can reference real-world values.

Multi-Cloud & ProvisioningIntermediate8 min readJul 9, 2026
Analogies

Data Sources Explained

A data source is a read-only query that fetches information from a provider or another Terraform state without creating or managing the underlying object. Unlike a resource block, which declares something Terraform should create, update, and destroy, a data block simply asks the provider API 'what does this look like right now?' and exposes the answer as attributes you can reference elsewhere in your configuration. This is essential when infrastructure is partially managed outside Terraform, when you need to look up dynamic values such as the latest AMI ID, or when one Terraform configuration needs to consume outputs produced by another.

🏏

Cricket analogy: A data source is like a commentator checking the scoreboard mid-over to report the current score without being able to change it — Terraform reads the AMI ID or account info the same way, purely as a lookup, never as a create-or-manage action.

hcl
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"
  subnet_id     = data.aws_subnet.selected.id
}

data "aws_subnet" "selected" {
  filter {
    name   = "tag:Tier"
    values = ["public"]
  }
}

How data sources fit into the dependency graph

Data sources participate in the same dependency graph as resources. Terraform reads a data source during the plan phase, and if that data source references an attribute of a resource that has not been created yet (for example, a security group ID computed at apply time), Terraform defers the read until after that resource is applied. This means a data source can be 'read now' or 'read after apply' depending on whether its arguments depend on unresolved computed values — Terraform figures this out automatically from the graph.

🏏

Cricket analogy: Just as an umpire waits for the third umpire's review of a run-out before confirming the score, Terraform defers reading a data source until a not-yet-created security group's ID is available after that resource applies.

Common data source patterns

Three patterns dominate real-world use: querying cloud provider metadata (latest AMI, available availability zones, current account ID via aws_caller_identity), consuming remote state outputs from another Terraform workspace via the terraform_remote_state data source, and looking up existing hand-created or legacy resources (an existing VPC, an existing DNS zone) so new resources can be attached to them without importing them into this state.

🏏

Cricket analogy: Like a captain checking the ICC's official player rankings (metadata), pulling last season's stats from a rival team's archive (remote state), and tagging an existing heritage stadium into this season's fixture list without rebuilding it (legacy lookup).

hcl
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "acme-tfstate"
    key    = "network/terraform.tfstate"
    region = "us-east-1"
  }
}

resource "aws_instance" "app" {
  subnet_id = data.terraform_remote_state.network.outputs.private_subnet_id
}

Think of a data source as a SELECT query against your infrastructure: it never mutates anything, it just returns rows (attributes) that your configuration can join against, refreshed on every plan unless you pin it with specific filters.

Data sources are re-evaluated on every terraform plan, which means a loosely filtered data source (e.g. 'most recent AMI') can silently change the plan output over time even though you changed nothing in your .tf files — always scope filters tightly for reproducible plans.

  • A data source (data block) performs a read-only lookup; it never creates, updates, or destroys infrastructure.
  • Data source arguments can depend on resource attributes, in which case Terraform defers the read until after apply.
  • terraform_remote_state lets one configuration consume the outputs of another, enabling multi-stack architectures.
  • Broad filters (like 'most recent AMI') cause plans to change between runs even without config changes — scope filters carefully.
  • Data sources are refreshed on every plan by default, keeping referenced values current with real infrastructure state.
  • Use data sources to reference resources managed outside your current Terraform state, avoiding unnecessary imports.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#DataSourcesExplained#Data#Sources#Explained#Fit#StudyNotes#SkillVeris