Protect the state stored in the bucket with a deliberately managed key.
The first dependency could not create itself.
Terraform uses state to connect configuration with the infrastructure it manages. For a team, that state needs a remote, restricted, and recoverable home. In CareFlow's AWS foundation, the intended home was S3—but the bucket did not exist until Terraform created it.
This was more than a clever interview question. State may contain sensitive values and infrastructure details. A lost, exposed, or concurrently modified state file can turn an ordinary change into a dangerous one.
Local state was acceptable once because “once” had an exit.
I isolated a bootstrap configuration whose only job was to create the remote-state foundation. It used local state for that first apply, then ordinary environment configurations initialized against the new S3 backend.
The exception did not become the operating model. It created the operating model.
State separation followed account separation.
Development, production, and security responsibilities already lived in separate AWS accounts. I carried that model into state with a dedicated state bucket per account rather than a shared universal store.
The purpose was not aesthetic symmetry. It kept access aligned to the environment: a development workflow did not need permission to read or change production state.
Four controls answered four different failure modes.
Support recovery from accidental deletion or human error.
Reject requests that do not use secure transport.
Coordinate writers so concurrent operations do not collide.
Current Terraform documentation supports S3 lock files with use_lockfile and describes DynamoDB-based locking as deprecated. That replaced an older pattern and removed another bootstrap resource. Locking remained essential; only its implementation changed.
A guardrail is useful only when its edge is understood.
I added Terraform's prevent_destroy lifecycle rule to reject an ordinary plan that would destroy the protected bucket. But HashiCorp documents an important limit: if the resource configuration is removed, the rule is removed with it.
So the lifecycle rule was one guardrail—not a substitute for versioning, restricted access, review, backups, or a recovery owner.
The bootstrap had to remain small enough to explain.
| Decision | Reason | Boundary |
|---|---|---|
| Local state for bootstrap | Break the circular dependency | Isolated, one-time path |
| S3 backend per account | Align access with environment ownership | No shared universal state store |
| S3 native lock file | Coordinate writers without another database | Still requires exact IAM permissions |
prevent_destroy | Reject routine destructive plans | Not protection after configuration removal |
Make exceptions expire.
A safe bootstrap is defined as much by its handoff as by its first apply.
State is control-plane data.
Its access, recovery, encryption, and coordination deserve explicit design.
Let state follow the boundary.
Environment separation weakens when every environment shares one broad state credential.
Know where a guardrail stops.
A documented limitation is more useful than an overstated control.
Before the first environment uses remote state.
- Is the local bootstrap path isolated and assigned an owner?
- Are encryption, versioning, transport policy, and access verified?
- Can concurrent writers acquire the intended lock?
- Does state access follow account and environment boundaries?
- Has the local-to-remote handoff been proven without exposing identifiers?
Documentation behind the implementation.
- HashiCorp: Terraform S3 backend
- HashiCorp: Backend configuration overview
- HashiCorp: Lifecycle meta-argument reference
This entry is educational, not security, compliance, or operational advice. It describes a dated CareFlow implementation; verify current platform behavior for your environment.
The infrastructure before the infrastructure.
A narrated walkthrough of the remote-state bootstrap, the controls around Terraform state, and the deliberate exit from the one-time local exception.