A Terraform resource creates, updates, or deletes infrastructure objects that Terraform manages directly. A data source only reads existing information and exposes it for use elsewhere in the configuration. In practice, resources define desired state, while data sources supply context such as IDs, attributes, or remote values that help other resources be configured correctly.
Why This Matters for Security Teams
Terraform’s split between resources and data source is easy to gloss over, but it determines whether a configuration is changing infrastructure or only reading from it. That distinction affects drift, ownership, approval flows, and blast radius. If a team models an existing object as a resource, Terraform may try to enforce state it does not truly own; if it models something as a data source, it may silently depend on external reality that can change outside the plan.
In practice, this is where many automation failures start, because the plan looks syntactically correct while the underlying control boundary is wrong. Teams also underestimate how quickly a “read only” lookup becomes a dependency chain for critical provisioning, especially when IDs, network details, or remote attributes are pulled from shared environments.
How It Works in Practice
A Terraform resource represents managed state. Terraform tracks the object in state, compares desired configuration with actual infrastructure, and then creates, updates, or destroys the object to converge on the declared outcome. That makes resources appropriate for things Terraform is expected to own over time, such as networks, compute, IAM constructs, databases, or security groups.
A data source is different: it queries something that already exists and returns attributes for use elsewhere. It does not create lifecycle ownership, and it does not try to reconcile the remote object to match configuration. Instead, it lets one part of the configuration consume facts about the environment, such as an account ID, a subnet ID, an AMI, a certificate, or a remote API value.
The practical test is ownership and intent. If Terraform should manage the object’s lifecycle, use a resource. If Terraform only needs the object’s current properties as input, use a data source. Common patterns include:
- Use a resource when the configuration must define the object’s desired state.
- Use a data source when the object is external, shared, or already managed elsewhere.
- Use a data source to avoid hardcoding environment-specific values that may differ across regions or accounts.
- Use resources carefully when importing existing infrastructure, because ownership must be explicit before Terraform can safely control changes.
This distinction matters most in shared platforms, where a lookup can succeed even though the referenced object is unmanaged, stale, or differently configured than the rest of the stack expects. These controls tend to break down when teams confuse “visible in the plan” with “actually governed by Terraform,” especially in environments with imported legacy infrastructure or shared cloud primitives.
Common Variations and Edge Cases
Tighter declarative control often increases coupling to state and ownership, so teams must balance repeatability against flexibility when deciding whether something belongs in Terraform state at all.
One common edge case is imported infrastructure. An object can start as external reality, then later become a resource after import, but that transition is a governance decision, not just a syntax choice. Another is the use of data sources for values that appear stable but are not, such as dynamically changing images or externally managed network attributes. Best practice is evolving here: the safer pattern is to treat data sources as live dependencies, not as frozen constants.
There is also a difference between “lookup for context” and “dependency for correctness.” A data source is harmless when it enriches configuration, but it becomes operationally significant when downstream resources rely on its output to build access paths, routing, or encryption settings. In those cases, the failure mode is not Terraform erroring, it is Terraform applying successfully against the wrong assumption.
Risk and Threat Considerations
The main risk is control-plane mismatch. A resource tells Terraform to own and enforce lifecycle, while a data source assumes the target already exists and remains valid. If that boundary is wrong, the result can be unintended modification of shared objects, hidden drift, or broken deployments that depend on external values remaining stable.
Failure mechanism: Teams misclassify an externally managed object as a resource, or a critical dependency as a data source, then Terraform either attempts to reconcile something it should not own or consumes stale attributes without detecting that the upstream object has changed.
Impact: Infrastructure can drift from policy, planned changes can fail late, and downstream systems may inherit incorrect IDs, access paths, or configuration values that are hard to trace back to the original lookup.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
NIST CSF 2.0 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | ID.AM — Asset Management | Resources and data sources both affect what infrastructure is tracked and depended on. |
| Recommendation — Inventory managed objects and external dependencies so Terraform ownership boundaries stay explicit. | ||
| CIS Controls v8 | CIS 4 — Secure Configuration of Enterprise Assets and Software | Terraform configuration choices directly shape repeatable, enforceable infrastructure state. |
| CIS 6 — Access Control Management | Misclassifying managed vs external objects can create unintended control over shared infrastructure. | |
| Recommendation — Standardize configuration as code so managed resources are controlled consistently across environments. Restrict who can alter managed infrastructure and who can only read external dependencies. | ||
Practitioner Guidance
Decision rule: If Terraform must create, replace, or retire the object, model it as a resource. If it only needs a current attribute from something owned elsewhere, use a data source and treat the output as an external dependency.
What to verify: Before trusting a data source, verify that the referenced object is stable, uniquely identified, and managed by the expected team or platform. Before trusting a resource, confirm that Terraform is the actual source of truth for lifecycle decisions, not just one consumer among many.
Common mistake: Treating a successful plan as proof of correct ownership. The harder question is whether Terraform should be allowed to change the object at all, or whether it should only observe it.
Practitioner takeaway: The resource versus data source decision is really an ownership decision, and getting it wrong creates either unauthorized control over shared infrastructure or blind dependence on external state.
Related resources from NHI Mgmt Group
- What is the difference between a classic portal resource and a newer portal resource in a Terraform provider?
- What is the difference between data source exposure through a public network and connecting data sources through a private tailnet path?
- What is the difference between resource discovery and code-to-resource mapping in Terraform operations?
- What is the difference between source control leakage and SharePoint secret exposure?
Deepen Your Knowledge
Reviewed and updated by the NHIMG editorial team on September 16, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org