Reconciliation & state without a state file

The control loop is the source of truth.

Intermediate12 min · lesson 4 of 12

Crossplane has no state file. The desired state lives in the Kubernetes API (the objects you applied), the actual state lives in the cloud, and a controller runs a reconcile loop that continuously compares them and drives reality toward the spec. This is the standard Kubernetes controller pattern applied to external infrastructure — the cluster’s etcd is the record, and reconciliation, not a periodic plan/apply, is how convergence happens.

The reconcile loop
1spec
desired, in the API
2observe
read the real cloud
3diff
desired vs actual
4act
create/update to converge
This loops forever. Change the cloud out-of-band and the next pass corrects it — self-healing infrastructure.

What no state file changes

It removes a whole category of problems Terraform users know well — no state file to store, lock, encrypt, or corrupt, and no “state drift” because reconciliation is continuous rather than a snapshot. It also changes the failure mode: instead of a plan that fails at apply time, you get objects whose conditions and events tell you, live, what the controller is doing and where the cloud API is refusing.

terminal
# delete the bucket directly in AWS; Crossplane notices and recreates it
$ aws s3 rb s3://acme-logs-prod --force
$ kubectl get bucket acme-logs-prod -w
acme-logs-prod False True # briefly not-ready...
acme-logs-prod True True # ...reconciled back into existence
Continuous reconciliation fights manual changes
Because Crossplane constantly enforces the spec, an out-of-band “quick fix” in the cloud console gets reverted on the next reconcile — which is the point, but surprising if you did not expect it. Make changes through the Kubernetes objects, not the cloud console; if you truly need to pause enforcement, that is what management/pause annotations are for, used deliberately.