Skip to content

Lifecycle Models

Every infrastructure tool takes a position on the lifecycle — how infrastructure is created, changed, reconciled, and retired — usually implicitly, and usually welded to the compiler so you can’t take one without the other. chant declines that bet: pluggable lexicons in, pluggable lifecycles out, pure synthesis in the middle. Bring your own lifecycle, and chant makes it durable.

This page makes the axes explicit so the rest of the docs can point here instead of re-deriving the argument. For the cost side of the trade — what an authoritative state file actually buys and charges — see State and Governance.

Any lifecycle model is a point in a three-dimensional space.

Truth lives in…CalledExamples
A state fileAuthoritativeTerraform, Pulumi
The live systemObservationalquery the cloud, diff against a snapshot
The source codeSource-as-truthGitOps reconcilers
DirectionNameWhat it does
code → cloudApplypush declared source into the live system
cloud → codeSyncpull live reality back into source (open PRs)
noneObservereport drift, change nothing
Answered byMechanism
A trusted state filethe tool consults its own record
A live ownership markera tag/label on the cloud resource
Nobodythe tool escalates rather than guessing

This third axis is the one most tools collapse into the first: they answer “is this mine?” from the same state file they host. chant separates them on purpose.

  • Truth is the live system. chant reads the cloud directly. The snapshot it stores is evidence for diffing, never a source of truth.
  • Reconciliation direction is a per-environment choice. A dev environment might only observe; staging might reconcile cloud → code; production might apply code → cloud behind a gate. Same project, different dial positions.
  • Ownership is answered by live markers. A chant-managed resource carries a marker — a standard tag or label — that records the stack identity on the resource itself. “Is this mine?” is answered by reading that marker, never by a record chant has to lock.
Two overlapping bands, Declared and Owned, on a Foreign field. Declared-only is to-create, the overlap is managed, Owned-only is the owned orphan where the delete-or-retain decision lives, and everything outside both bands is foreign and never touched. Two overlapping bands, Declared and Owned, on a Foreign field. Declared-only is to-create, the overlap is managed, Owned-only is the owned orphan where the delete-or-retain decision lives, and everything outside both bands is foreign and never touched.
Declaration and ownership are two overlapping sets. A delete is only possible where a resource is owned but no longer declared — everything outside both is foreign.

Declaration is your source — what your TypeScript exports. Ownership is a fact recorded on the live resource — a marker chant reads, never a record it locks. Because the two are separate, dropping a resource from your source does not by itself delete it. chant lifecycle plan proposes a delete only for a resource that is owned and no longer declared. Three levers decide what happens to it.

  • ApplyOp delete: "never" — stack-wide. Apply never prunes, so an undeclared resource is left alone.
  • Strip the marker — per-resource. The prune is marker-scoped, so an unmarked resource is foreign and never touched.
  • Spec-true retain — the target spec’s own knob. CloudFormation DeletionPolicy: Retain, the K8s prune selector. chant passes it through rather than inventing one.

No hosted state file decides this. A resource lives or dies based on what you declare and what its live marker says, which is why the snapshot can be deleted between runs with no change in behavior.

The three axes collapse, in practice, into one dial chosen per environment:

observe → reconcile → authoritative
(report) (cloud→code (code→cloud
PRs) apply)
  • observechant lifecycle diff --live / WatchOp. Detect drift, change nothing.
  • reconcileReconcileOp. Open PRs that pull live reality back into source.
  • authoritativeApplyOp. Push declared source into the cloud, deleting owned orphans.

You turn the dial up per environment as trust and tooling allow. Nothing forces an environment past the position you chose for it.

There is exactly one rule that prevents this model from quietly becoming the thing it avoids:

The projection reads ownership from the live marker, never from the snapshot.

The moment a mutation trusts the snapshot — uses it to decide what to create, update, or delete — the snapshot becomes load-bearing, and you have rebuilt an authoritative state file under a different name, with all its costs. chant’s change set (chant lifecycle plan) reads ownership only from the live resource. The snapshot can be deleted between runs with no change in behavior. That is the test, and chant holds to it by construction.