LibreInfra Field Notes
Infrastructure as code is only as ownable as its state
Declarations describe intention; state, providers and execution identity decide whether change remains safe.
Infrastructure as code is only as ownable as its state
The configuration files describe intended infrastructure. The state, providers, credentials and execution path determine whether the organisation can safely understand and change what already exists.
The repository looks complete.
Networks, databases, identities and compute resources are declared as code. Changes pass through review. Plans are attached to pull requests. The team can point to modules, naming rules and automated pipelines.
Then the remote state backend becomes unavailable.
Nobody knows which workspace controls which resources. A provider upgrade changes how several objects are interpreted. Resources created manually cannot be matched confidently to declarations. The pipeline account has expired, and local execution would require privileges no operator should hold permanently.
The code remains available.
Safe control of the infrastructure does not.
The central test
Infrastructure as code becomes ownable when the organisation controls the full change system: declarations, state, providers, execution identity, review, drift, recovery and transfer.
Code describes intention; state connects it to reality
Tools such as OpenTofu and Terraform compare declared configuration with a representation of existing infrastructure.
That representation is state.
State connects a resource in code to a real object in an external system. It may contain identifiers, dependencies, attributes, outputs and information required to calculate the next change.
Treating it as a disposable cache is dangerous.
Without the correct state, the same declaration may try to create a duplicate resource, fail to recognise an existing one or propose replacement of infrastructure that should remain in place.
Common mistake
Treating version-controlled configuration as the complete source of truth.
Better framing
Treat code as intended state, the infrastructure provider as observed state, and the state file as the controlled relationship between them.
All three matter.
Declared configuration
|
v
Plan engine
/ \
v v
State record Provider API
\ /
v v
Proposed change
|
v
Controlled execution
|
v
Updated infrastructure
|
v
Updated evidence
A failure anywhere in that loop can produce a system that is still running but no longer safely manageable.
State is production data
State may reveal infrastructure attributes, internal addresses, resource identifiers and sensitive outputs.
More importantly, it carries control relationships.
Changing or losing state can change how the tool behaves toward production.
That means state needs the same treatment as other critical operational data:
- controlled access
- locking
- version history
- backup
- integrity
- recovery testing
- retention
- clear ownership
The state backend is part of the production control plane even when no application reads from it.
Its failure may not stop current services immediately. It can stop the organisation from changing, recovering or replacing them safely.
The recovery procedure should answer more than “restore the latest file”.
Which version corresponds to the current infrastructure? Were changes in progress when the backup was taken? Can locks be recovered safely? What evidence shows that the restored state matches the provider’s observed resources?
A technically valid state file may still be operationally wrong.
Providers are part of the executable architecture
Infrastructure code does not speak directly to every platform.
Providers translate declared resources into API operations.
They interpret schemas, defaults, lifecycle behaviour and differences between versions. Upgrading a provider can therefore change the meaning of an existing configuration even when the code has not changed.
A provider may begin tracking an attribute that was previously ignored. A default may change. An older resource type may be replaced by a new one. Import behaviour may differ.
Provider versions belong in the architecture record.
The organisation should know:
- which provider and version produced the current state
- where provider packages are obtained
- how integrity is verified
- which API permissions they exercise
- how upgrades are tested
- whether older versions remain obtainable for recovery
A configuration that depends on a provider release no longer available from its original source may be difficult to reconstruct during an incident.
Mirrors, controlled caches or approved artifact stores can reduce that dependency.
The aim is not to freeze providers forever.
It is to ensure that changing the toolchain remains a deliberate infrastructure change.
A plan is a proposal, not proof
Infrastructure plans are useful because they show what the tool expects to change.
They are not guarantees.
The observed environment may change between planning and execution. Data sources may return different values. A provider API may apply defaults. Credentials may have access to more resources than the plan reveals. External automation may modify the same system concurrently.
A reviewed plan can therefore become stale.
The execution path needs to preserve the relationship between:
- the configuration revision reviewed
- the state version used
- the provider versions used
- the plan approved
- the identity that executed it
- the result returned by the provider
- the state written afterward
A pipeline that recalculates the plan during execution may apply changes different from those reviewed.
A pipeline that applies an old saved plan may act on an environment that has changed materially.
There is no universal answer for every system.
There should be an explicit rule.
Operational test
Select a recent infrastructure change and reconstruct exactly which source revision, state version, provider packages, plan and execution identity produced the final result.
If the answer depends on several people remembering what happened, the change system is not producing sufficient evidence.
Execution identity defines the real blast radius
Infrastructure automation often receives broad privileges.
It may create networks, grant roles, rotate credentials, change databases and destroy resources across an entire account or estate.
The code may declare only a small change while the execution identity can do far more.
That makes credential design part of infrastructure-as-code safety.
A strong execution model separates:
- planning access from modification access
- development from production
- ordinary change from emergency recovery
- unrelated resource domains
- human approval from machine execution
The tool should not have authority simply because a module might need it one day.
Privileges should reflect the state boundary being changed.
If one state file contains networking, identity, databases and application infrastructure, the execution path may need authority over all four. A failure or compromised pipeline then receives a very large blast radius.
State boundaries are therefore also security boundaries.
They should be chosen by lifecycle, ownership and failure impact—not merely by repository layout.
Modules can hide the contract they are meant to simplify
Modules reduce repetition and make common patterns easier to apply.
They can also hide important infrastructure decisions behind convenient inputs.
A module may create logging, identity, backups, network rules and encryption in addition to the resource named in its title. A small version change can therefore affect several operational responsibilities.
Consumers need to understand the contract of a module:
- what it creates
- what it expects to exist
- what it owns
- what may be changed externally
- which outputs are stable
- which changes require replacement
- how data is protected before destructive operations
- how the module is upgraded or retired
A module should simplify use without making consequences invisible.
Internal modules create another maintenance responsibility.
Once several teams depend on one abstraction, its maintainers are operating a platform interface. They need versioning, testing, compatibility rules and a transfer path.
A module copied into many repositories avoids central dependency by creating uncontrolled divergence.
A shared module avoids divergence by creating a central dependency.
The correct choice depends on whether that dependency is owned.
Drift is not solved by running apply more often
Drift occurs when observed infrastructure differs from declared configuration or recorded state.
Some drift is unauthorised change.
Some comes from external controllers, automatic scaling, provider defaults or normal runtime behaviour. Some represents emergency action that was necessary but never reconciled into code.
Automatically applying configuration can remove drift.
It can also remove a legitimate operational change or recreate a harmful configuration repeatedly.
The organisation needs to classify differences before deciding how to act.
Useful categories include:
- expected runtime variation
- provider-managed attributes
- emergency change awaiting reconciliation
- unauthorised manual change
- external-controller ownership
- stale declaration
- state corruption
The correct action may be to update code, import a resource, adjust lifecycle rules, remove manual change or hand ownership to another controller.
“Run apply” is not a drift policy.
It is one possible enforcement action.
State recovery should be rehearsed before it is needed
Losing state does not always mean losing infrastructure.
It means losing the trusted relationship between declarations and infrastructure.
Reconstruction may involve restoring a backend backup, importing existing resources or rebuilding part of the environment under a new state boundary.
Each path carries risk.
Importing resources can reconnect code to real objects, but it may not reproduce every historical dependency or lifecycle decision. Rebuilding may produce a cleaner state while requiring carefully ordered replacement. Restoring an old state may reintroduce references to resources that have changed since the backup.
A recovery exercise should therefore be performed in a representative environment.
It should test:
- access to backend backups
- state integrity
- provider availability
- lock recovery
- comparison with observed infrastructure
- import or reconciliation procedures
- controlled resumption of change
The objective is not merely to open the state file.
It is to regain safe authority over the infrastructure.
A practical infrastructure-as-code review
| Area | Weak signal | Stronger evidence |
|---|---|---|
| Configuration | Infrastructure is stored in Git | Declarations, ownership and lifecycle boundaries are explicit |
| State | A remote backend is used | Access, locking, backup, integrity and recovery are tested |
| Providers | Versions are constrained | Packages, compatibility and upgrade paths are controlled |
| Planning | Plans appear in pull requests | Reviewed source, state and provider versions are tied to execution |
| Identity | A pipeline account exists | Scoped execution roles reflect state and environment boundaries |
| Modules | Common patterns are reusable | Module contracts, versions and destructive effects are understood |
| Drift | Scheduled plans run | Differences are classified before enforcement |
| Recovery | State backups exist | The organisation has rehearsed restoration or import |
| Evidence | Changes are logged | Source, plan, identity, provider result and final state are connected |
| Transfer | The repository is documented | Another team can plan, apply, recover and upgrade safely |
The goal is not to maximise the amount of infrastructure represented as code.
Some systems may be better managed through other controllers or specialised operational tools.
The goal is to ensure that every change path has one clear authority and a recoverable record.
The code should make control safer, not merely faster
Infrastructure as code is valuable because it can make changes reviewable, repeatable and transferable.
Those properties disappear when state is fragile, providers are uncontrolled, execution identities are too broad or modules conceal their operating consequences.
The repository is the visible part of the system.
Ownership sits in the complete loop from intention to observed result.
A well-designed change system allows the organisation to understand what exists, propose a change, bound its authority, verify the outcome and recover the control plane itself.
Anything less is automation attached to infrastructure, not infrastructure under control.
One question for the next architecture review
Choose the most critical infrastructure state and ask:
If its backend, usual pipeline and original maintainers became unavailable, could another team reconstruct the trusted relationship between code and real resources without risking an unintended replacement?
Make the next decision with clarity