Crisp answer: Data sources let you read information about existing infrastructure or external systems without managing it. The result can be used in resource arguments just like any other reference.
Why data sources:
You might not manage everything in the same Terraform root. Your VPC might be in a separate Terraform config, or an AMI ID changes and you want to always use the latest without hardcoding it. Data sources solve this.
Common data sources:
# Look up the latest Ubuntu 24.04 AMI
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical's AWS account
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-24.04-amd64-server-*"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id # always latest
instance_type = "t3.micro"
}
# Look up an existing VPC by tag
data "aws_vpc" "main" {
tags = {
Name = "production-vpc"
}
}
resource "aws_security_group" "app" {
vpc_id = data.aws_vpc.main.id
}
# Look up availability zones in the current region
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "private" {
count = 2
availability_zone = data.aws_availability_zones.available.names[count.index]
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
vpc_id = aws_vpc.main.id
}
# Get current AWS account ID and region
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
resource "aws_iam_role_policy" "example" {
policy = jsonencode({
Statement = [{
Resource = "arn:aws:s3:::my-bucket-${data.aws_caller_identity.current.account_id}"
}]
})
}
# Read a Secrets Manager secret
data "aws_secretsmanager_secret_version" "db" {
secret_id = "prod/database/password"
}
Difference between data sources and resources:
resource |
data |
|
|---|---|---|
| Creates infrastructure | Yes | No — read only |
| Manages lifecycle | Yes (update/destroy) | No |
| In state | Yes | Referenced at plan time |
| Prefix in references | aws_vpc.main.id |
data.aws_vpc.main.id |
What to say in the interview:
"Data sources are read-only queries against existing infrastructure or external systems. I use them constantly for things like looking up the latest AMI so I don't hardcode IDs, reading availability zones for the current region, and looking up the AWS account ID for ARN construction. The important distinction: a data source reads something Terraform doesn't manage. A resource is something Terraform creates and is responsible for. References to data sources always start with data dot."