A Terraform configuration can describe a network:
resource "example_network" "bfstore_dev" {
name = "bfstore-dev"
cidr = "10.20.0.0/16"
}
The configuration gives the resource an address inside Terraform:
example_network.bfstore_dev
The cloud platform gives the real network a different identity:
network-7f31c2
Terraform needs to remember that these two names refer to the same logical resource.
TERRAFORM ADDRESS
example_network.bfstore_dev
│
▼
REMOTE RESOURCE
network-7f31c2
That relationship lives in Terraform state.
Without it, Terraform can still read the configuration, and the network can still exist in the cloud. What disappears is Terraform’s memory that this configuration block owns that particular network.
That changed how I think about the state file:
Terraform state is an infrastructure-management database. It records which real objects Terraform believes belong to the declared configuration.
It is not a database in the conventional application sense. It is a persisted management record whose most important job is preserving resource identity and ownership.
It is not the infrastructure itself, a complete copy of the cloud platform, or the desired design. It is the operational memory connecting the design to objects that exist independently.
Understanding that relationship explains not only why Terraform needs state, but also how teams should secure, divide, recover and transfer it.
Configuration, state and reality
Terraform infrastructure has three important representations.
CONFIGURATION
What should be managed?
STATE
Which real objects does Terraform believe
correspond to that configuration?
REMOTE SYSTEM
What currently exists?
A plan compares those views.
CONFIGURATION
│
├──────────┐
│ │
▼ ▼
STATE REMOTE READ
│ │
└────┬─────┘
▼
PLAN
Suppose configuration says:
catalog replicas:
3
State remembers the remote resource identity:
resource:
deployment-8821
The platform currently reports:
catalog replicas:
5
Terraform can propose:
~ replicas: 5 -> 3
Each layer contributes something different.
Configuration supplies intention. State supplies identity and persisted information. The provider reads the remote platform. The plan describes the proposed reconciliation.
State is therefore not the final authority on what exists.
Suppose state records a network, but an operator has manually deleted it. The state entry does not keep the network alive. During planning or refresh, Terraform can discover that the remote object is missing and may propose creating a replacement.
Similarly, a remote object may have been changed outside Terraform. State records what Terraform knows, while the remote platform remains authoritative for its current condition.
A useful wording is:
State is Terraform’s authoritative memory of ownership and identity, not the remote platform’s final authority on existence.
State preserves identity and observed values
The most important job of state is mapping configuration addresses to remote objects.
module.network.example_subnet.private_a
│
▼
subnet-4c9217
Terraform cannot reliably rediscover resources using names alone. Names may be duplicated, changed, generated, absent, locally scoped or shared with unmanaged resources. Remote identifiers provide a more precise connection.
The state database answers:
Which remote object was most recently recorded for this resource address?
State commonly contains more than remote IDs. It can include:
resource address
provider association
remote resource ID
persisted resource attributes
computed values
dependency information
output values
resource metadata
For example, the cloud provider may allocate an address:
10.20.10.14
or generate an endpoint:
catalog-db.internal.example
Terraform may persist those values so other resources and outputs can refer to them.
output "database_endpoint" {
value = example_database.catalog.endpoint
}
This makes state useful for later planning. It also makes state potentially sensitive.
State makes lifecycle operations possible
State gives Terraform the ownership information needed for import, refactoring, deletion and handover.
Losing state
Suppose bfstore’s network is running normally and its state file is lost.
CLOUD PLATFORM
network exists
subnets exist
routes exist
TERRAFORM
state unavailable
The infrastructure continues carrying traffic. It exists independently of Terraform.
But Terraform no longer knows that those objects satisfy the configuration. A new plan may attempt to create replacements:
+ create network bfstore-dev
+ create private subnet A
+ create private subnet B
The platform might reject the changes because names or CIDR ranges already exist, or it might allow duplicates.
The infrastructure survives state loss. Safe automated management may not.
Importing an existing object
If the real resource still exists, Terraform can associate it with a configuration address through import.
EXISTING RESOURCE
network-7f31c2
│
▼
IMPORT
│
▼
TERRAFORM ADDRESS
example_network.bfstore_dev
Import establishes or reconstructs the identity mapping. It does not prove that the written configuration matches the remote resource.
After import, a plan may reveal differences:
CONFIGURATION
CIDR:
10.20.0.0/16
REMOTE RESOURCE
CIDR:
10.30.0.0/16
A careful recovery process is:
- identify the correct remote object
- write or verify its configuration
- import it into the correct address
- produce a plan
- inspect every proposed change
- reconcile differences deliberately
Import is a state reconstruction operation. It should be treated with the care of a database recovery.
Refactoring resource addresses
Suppose a resource begins at:
example_network.bfstore_dev
It is later moved into a module:
module.network.example_network.this
The real network has not changed, but its Terraform address has.
Without recording that move, Terraform may interpret the configuration as:
old resource removed
new resource added
The plan could propose:
- destroy example_network.bfstore_dev
+ create module.network.example_network.this
Terraform supports mechanisms for moving addresses while preserving their relationship to existing remote objects.
Refactoring infrastructure code can alter state identity even when the intended infrastructure remains unchanged.
Infrastructure refactoring must preserve management identity, not just intended behaviour.
Deletion and ownership removal
Suppose this block is deleted:
resource "example_subnet" "obsolete" {
cidr = "10.20.90.0/24"
}
State remembers which real subnet belonged to that address, so Terraform can propose:
- destroy subnet-93ae12
Without state, the absence of a block would not identify which remote object should be deleted.
Sometimes the resource should remain in the cloud but stop being managed by one Terraform state. Examples include moving it to another state, transferring it to another team, adopting a different management system, or retaining it during a migration.
Removing the state association says:
Stop managing this remote object
through this configuration address.
It does not necessarily say:
Delete the remote object.
That operation needs a clear handover. Otherwise the resource becomes an orphan: still running, still costing money and still carrying risk without a clear owner.
State manipulation changes management responsibility.
State is control-plane data
State may be small, but its operational importance is much larger than its byte count suggests.
Sensitive values
Suppose Terraform creates a database and receives a generated password or connection string. Even when command output hides the value, the provider may store it in state.
State can also contain credentials, private endpoints, certificates, user-data scripts, connection details, generated tokens and sensitive outputs.
Marking an output as sensitive reduces accidental display. It does not necessarily remove the underlying value from state.
CLI OUTPUT
value hidden
STATE
value retained
State should therefore be protected like a sensitive operational database. That includes access control, encryption in transit and at rest, audit logging, backup access, retention and secure deletion.
A state file committed to a public Git repository is not merely untidy. It can be a credential incident wearing a .json coat.
Shared state and locking
Terraform can keep state in a local file:
terraform.tfstate
That is convenient for experiments and individual learning. It becomes fragile when several actors manage the same environment.
ENGINEER A ENGINEER B CI PIPELINE
│ │ │
└───────────────┼───────────────┘
▼
REMOTE BACKEND
│
▼
SHARED STATE
A shared backend gives the workflow one common state location and should coordinate writers. Suppose two applies both read version 41. Run A writes version 42; Run B, still working from 41, then attempts to save its result.
A backend with locking can allow one cooperating writer at a time.
Locking does not prevent every conflict. It does not stop console changes, another infrastructure tool, external automation, or a separate state managing the same object. It protects Terraform operations that participate in the same locking system.
Conflicting ownership
Suppose state A and state B both believe they own the same security group.
STATE A
│
▼
security-group-71
▲
│
STATE B
Configuration A allows HTTPS only. Configuration B allows HTTPS and SSH. Each apply may undo the other.
The problem is not corrupted syntax. It is conflicting ownership.
Each remote object should normally have one clear management authority for each controlled property.
State boundaries are ownership boundaries.
The backend as infrastructure
Once state moves to a remote backend, that backend becomes part of the platform’s control infrastructure.
If it is unavailable, existing resources continue running, but Terraform planning and applying may be blocked.
If it is compromised, resource identities, sensitive attributes and management history may be exposed or altered.
If it is lost, the infrastructure remains, but safe automated ownership may disappear.
The backend therefore needs its own operating model:
access policy
encryption
versioning
locking
backup
restore testing
audit
monitoring
break-glass access
The tool managing infrastructure depends on infrastructure of its own. That circularity is not unusual, but it needs to be acknowledged.
State boundaries and infrastructure APIs
One enormous state can contain an organisation’s networking, identity, databases, clusters, applications and observability.
That gives Terraform a broad view, but it also creates a broad blast radius. A small change may require reading the complete state, using broad cloud permissions, locking unrelated work and exposing many sensitive values.
Splitting state can reduce those problems.
Possible boundaries include:
account or subscription
environment
region
platform layer
team ownership
resource lifecycle
security boundary
Smaller states introduce coordination between layers. Larger states introduce coupling inside one management boundary.
The right division groups resources that genuinely:
- change together
- share ownership
- require the same permissions
- have related lifecycles
- need one coordinated plan
A state boundary should be an architectural decision, not a side effect of whichever directory was created first.
Outputs are contracts
One state may need information produced by another.
NETWORK STATE
│
▼
OUTPUT CONTRACT
│
▼
WORKLOAD STATE
The network state might expose network IDs, private subnet IDs or security boundary IDs. A workload state consumes those values.
This is useful composition, but it creates coupling. Renaming an output can break consumers. Changing its meaning can be worse.
An output named:
private_subnet_ids
should not quietly change from application subnets to database subnets.
Infrastructure outputs behave like APIs. They need intentional names, documented meaning, controlled evolution, minimal exposure and clear ownership.
Sharing raw state broadly merely to obtain one output may expose more information than the consumer needs.
A possible bfstore design
Suppose bfstore begins with separate AWS infrastructure layers.
aws/
├── organisation/
├── network/
├── shared-services/
├── observability/
└── workloads/
Each environment or account boundary might use a separate state.
bfstore-aws-organisation
bfstore-aws-network
bfstore-aws-shared-services
bfstore-aws-observability
bfstore-aws-dev-workloads
bfstore-aws-staging-workloads
bfstore-aws-prod-workloads
The organisation state owns accounts and high-level policies. The network state owns IP allocation, transit networking, shared DNS and central egress. Shared services owns platform tooling, while workload states own environment-specific application infrastructure.
The network state exposes only the outputs workloads need. Production can also use separate credentials and approval rules from development.
This creates management boundaries, not merely tidy folders.
Recovery and safe state operations
A versioned backend can preserve earlier state versions. That history can help answer:
Which resource IDs existed before the failed apply?
Which output changed?
When did this object disappear from state?
Which state version was last known to be healthy?
State history supports investigation, but it may also contain historical secrets and deleted infrastructure metadata. Retention needs both recovery and security consideration.
Restoring an older state version is not the end of recovery. The remote infrastructure may have changed since that version was created.
RESTORED STATE
version 40
REMOTE PLATFORM
contains changes from versions 41 and 42
A safe recovery process includes:
- stop concurrent writers
- preserve the damaged and candidate state versions
- identify the last trustworthy state
- compare it with remote infrastructure
- produce a carefully reviewed plan
- import, move or remove associations where required
- resume automation only after ownership is understood
State restoration is reconciliation between memory and reality.
Terraform state is serialised data and can technically be edited, but arbitrary text editing is not a sensible workflow. A mistake can point an address at the wrong object, orphan infrastructure, create duplicates or produce a destructive plan.
Terraform provides supported mechanisms for moving addresses, removing associations, importing objects and inspecting state. These operations still need review and backups, but preserve more of Terraform’s expected structure than direct editing.
A compact state checklist
| Area | Question |
|---|---|
| Identity | Which remote object belongs to each Terraform resource address? |
| Backend | Where is state stored, and who operates that system? |
| Access | Who can read or modify state? |
| Sensitivity | Which secrets or private infrastructure details can it contain? |
| Protection | How is it encrypted in transit and at rest? |
| Locking | Can two applies write the same state concurrently? |
| Versioning | Can an earlier version be recovered? |
| Restore | Has the recovery process been practised? |
| Ownership | Can another state or system change the same resource? |
| Boundaries | Do resources in this state share ownership, permissions and lifecycle? |
| Drift | How are remote changes discovered and resolved? |
| Imports | How are existing objects safely associated with configuration addresses? |
| Refactoring | How will addresses move without recreating infrastructure? |
| Handover | What happens when a resource leaves this state but remains in service? |
| Outputs | Which values form contracts with other infrastructure layers? |
| Deletion | Which remote object will Terraform destroy when an address is removed? |
| Recovery authority | Who may perform emergency state operations? |
The mental model I am keeping
My earlier model was:
TERRAFORM STATE
a cache Terraform generates
after apply
The stronger model is:
CONFIGURATION
│
▼
RESOURCE ADDRESS
│
▼
STATE
│
├── remote identity
├── persisted attributes
└── management metadata
│
▼
REMOTE RESOURCE
Configuration answers:
What should Terraform manage?
State answers:
Which real objects does Terraform
believe satisfy that declaration?
The provider reads what currently exists, and the plan proposes how to reconcile the views.
Terraform state is not merely a receipt produced after creation. It remembers the relationship between declared resources and independently existing objects.
The platform can survive without it: networks route packets, databases store rows and clusters run Pods. But Terraform may no longer know which objects are its responsibility.
Configuration tells Terraform what kind of world we intend.
State is how it recognises that world when it sees it again.
References and further reading
Terraform state Introduces Terraform state and its role in mapping configuration to remote infrastructure.
The purpose of Terraform state Explains resource identity mapping, metadata, performance and synchronisation.
Terraform backends Documents state-storage configuration and remote backend behaviour.
Terraform state locking Explains how supported backends prevent concurrent state-writing operations.
Sensitive data in Terraform state Discusses sensitive values, local state and backend security considerations.
Terraform import Documents associating existing remote resources with Terraform resource addresses.
Terraform state command Documents supported commands for inspecting and modifying Terraform state associations.
Terraform moved blocks Explains preserving resource identity while refactoring configuration addresses.