Resources vs Data Sources
Scenario: Two separate teams each declare the same shared company network as a resource in their own independent Terraform state, and both genuinely believe they are the one responsible for its lifecycle.
You've used resource blocks throughout this track, but Terraform has a second, equally important block type: data. The difference is about ownership, and getting it right prevents exactly the incident above. A resource block means "Terraform should create this object if it doesn't exist, and manage its lifecycle from now on - including destroying it if the block is removed." A data block means "this object already exists, owned by someone or something else; just read its current attributes so I can use them." A data source has no create/update/destroy behavior at all - it's a read-only lookup.
Critically, this is a statement about who owns the lifecycle, not about whether the object happens to already exist right now: perfectly real, already-existing infrastructure can still become a Terraform-managed resource through import (a whole module later in this track). The rule of thumb is simple: if this configuration should be allowed to destroy the object, it's a resource; if it should only ever read from it, it's a data source. Reads from a data block usually happen early, during the plan's refresh step, but if the data source's own arguments depend on another resource's output, Terraform correctly defers that lookup until apply time, once the dependency is known.
Analogy: Aresourceis an asset entry on your own company's inventory ledger - you bought it, you're responsible for it, you can dispose of it. Adatasource is a directory lookup - looking up a courthouse's address and opening hours does not make you its owner, and you certainly can't order it demolished.
A worked configuration
data "fakecloud_network" "shared" {
name = "platform-network"
}
resource "fakecloud_server" "api" {
name = "api"
network_id = data.fakecloud_network.shared.id
}
Ambiguous lookups are a genuine production hazard: a data block that searches by a loose filter (say, a common tag) rather than a stable unique name or ID can silently match the wrong object if a second one is created later with a similar tag - and because it's just a read, Terraform won't warn you, it will happily wire your server to whatever network the filter matched. Query by the most specific stable identifier available, and document in a comment or README which team or state actually owns each shared object your data blocks depend on.
Common mistakes in production
- Declaring the same real-world object as a
resourcein two different Terraform configurations - both will believe they own it, and one will eventually try to "correct" a change the other legitimately made. - Writing a
datasource filter loose enough to match more than one real object (e.g. by a common tag instead of a unique name) - it can silently bind your infrastructure to the wrong object with no error at all.
Goal: Treat the plan as a change contract: understand every create, update, replacement, and destroy before approving it. Reinforce this lesson in the tf-data-source-discovery Terraform lab. Open/labs/terraformand choose slugtf-data-source-discovery; the lab runs real Terraform against the offline FakeCloud provider.