Terraform configuration · 14 min read · Reviewed 2026-08-29

Terraform Data Sources vs Resources: When to Use Each

A resource block tells Terraform to manage an object. A data block asks a provider for information about an object that already exists. They can look similar in a configuration, but they express different ownership: confusing them can lead to duplicate infrastructure, fragile IDs, or a plan that is hard to explain.

Reading a shared network, managing an application subnet

The data source only reads the existing VPC. The resource block is the configuration that owns the new subnet and its lifecycle.

data "aws_vpc" "shared" {
  tags = { Name = "shared-network" }
}

resource "aws_subnet" "application" {
  vpc_id     = data.aws_vpc.shared.id
  cidr_block = "10.0.10.0/24"
}

Managed resources and read-only lookups have different jobs

A resource block represents infrastructure Terraform is responsible for creating, updating, or destroying. Its address is tracked in state, and its lifecycle is part of every future plan. Use a resource when the configuration is the deliberate source of truth for that object.

A data block reads information made available by a provider or another external source. It does not create or modify the queried object. In the example, the VPC belongs to a shared network pattern, while this configuration creates only the application subnet inside it.

Choose ownership before choosing syntax

The most useful question is not “can I look this up?” but “who is allowed to change it?” A platform team may manage the network, while an application team receives its ID or discovers a specifically tagged shared network. The boundary should be documented and stable enough to review.

Do not use data sources as a shortcut around missing design decisions. If several VPCs might match a lookup, or a name is routinely reused, the configuration can select the wrong object. Prefer a precise provider-supported filter, a well-defined input, or an explicit module interface.

Data sources can affect the timing of a plan

Terraform normally tries to read data sources while planning. If a data source argument depends on a value Terraform cannot know until a managed resource is created or changed, Terraform may defer that read until apply. Terraform shows this in the plan output.

That does not automatically mean the configuration is wrong, but it is a signal to inspect the dependency. A deferred lookup can make downstream values unknown in the plan, reducing the confidence a reviewer has before approving an apply.

Use explicit interfaces between configurations

For reusable modules, outputs are often clearer than having a child module search broadly for infrastructure. A network module can output a VPC ID; a caller passes that value into an application module. The relationship is visible, testable, and does not rely on a naming convention hidden in a data lookup.

For separate teams or workspaces, choose a governed interface appropriate to the organisation. Keep access narrow, document the contract, and avoid turning state files into an informal catalogue of unrelated systems.

Put it into practice

Draw a boundary around one shared network and one application workload. Decide which objects the application configuration should manage, which it may read, and what exact identifier or output makes that boundary reliable.

  1. Identify which team owns the existing cloud object.
  2. Use a resource when this configuration should create and change it.
  3. Use a data source only to read an existing, clearly identified object.
  4. Review the plan and confirm the lookup is not unexpectedly deferred to apply.

Frequently asked questions

What is the difference between a Terraform data source and a resource?

A resource block manages infrastructure Terraform creates, changes, or destroys. A data block reads existing information from a provider or external source and does not create or modify the queried object.

Should I use a data source to find a shared VPC or virtual network?

It can be appropriate when another team owns a single, clearly identified network. Use a precise supported filter or a documented input and make the ownership boundary explicit; a broad name lookup can select the wrong object.

Why can a Terraform data source be read during apply instead of plan?

Terraform defers a data source when its arguments depend on a value that is unknown until a managed resource is created or changed. The plan displays this, so review the dependency and its effect on unknown downstream values.

Continue with Terraform Architect