skip to content

In a Flux v2 Kustomization resource, what do the interval and prune fields control, and what happens if prune is left false?

level: juniorimportance: should knowfreq 58%

answer

  1. one field is a clock, one is a policy
  2. re-apply happens even with no commit
  3. that periodic re-apply is the drift fix
  4. removal in Git versus removal in cluster
  5. Flux keeps an inventory of what it applied

basics

~20 s

interval sets how often kustomize-controller rebuilds and re-applies the manifests even when Git has not changed, which is what corrects drift. prune: true lets Flux delete cluster objects it previously applied once they disappear from the source.

solid answer

~50 s

`interval` is the resync period for that Kustomization. kustomize-controller reconciles when a new source revision arrives *and* every `interval` regardless, re-applying the built manifests. That periodic re-apply is what makes Flux self-healing: a hand edit to a Flux-managed field is overwritten at the next tick. `prune` decides what happens to *removals*. Flux records an inventory of every object it applied for that Kustomization; with `prune: true`, an object that is in the inventory but no longer in the built output gets deleted from the cluster. With `prune: false` — the default — deleting a manifest from Git leaves the live object running forever, so Git stops being an accurate description of the cluster and you accumulate orphans nobody remembers creating. The catch is symmetric: with prune on, a mistake that makes a path build to fewer objects — a bad kustomize edit, the wrong `path`, a suspended-then-resumed tenant — becomes a deletion.

code

bash · 8 lines
bash
# pause reconciliation before a risky refactor of the manifests
flux suspend kustomization apps

# see what the new revision would change before merging
flux diff kustomization apps --path=./apps/production

# resume normal 10m reconciliation
flux resume kustomization apps

go deeper

for a junior

Say plainly that interval is how often Flux re-applies the manifests, and that prune must be enabled for deleting a file from Git to delete the object from the cluster.

for a middle

Explain that the periodic re-apply is the drift-correction mechanism, and that pruning works from an inventory of previously applied objects rather than by comparing Git history.

for a senior

Talk about blast radius: which resources you are willing to let prune delete, separating stateful paths into their own Kustomization, and using suspend and a rendered diff before merging structural changes.

for a principal

Set the fleet policy — prune on by default so Git stays truthful, with explicit carve-outs for irreplaceable state, plus interval budgets that keep API server load sane across hundreds of Kustomizations.

## Two different questions A GitOps controller must answer two questions that people often blur together. *How often do I re-assert the desired state?* and *what do I do about things that used to be desired and no longer are?* In Flux, the first is `interval` and the second is `prune`, and they live on the `Kustomization` resource in `kustomize.toolkit.fluxcd.io`. ## interval: the resync clock ```yaml apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: apps namespace: flux-system spec: interval: 10m path: ./apps/production prune: true sourceRef: kind: GitRepository name: fleet ``` kustomize-controller reconciles this object on two triggers: the source published a new artifact revision, or `interval` elapsed. On either, it builds `path` from the current artifact and applies the result with server-side apply. The second trigger is the interesting one. Nothing in Git changed, yet Flux applies again. That is the drift-correction mechanism: if somebody ran an imperative edit against a field Flux owns, or another controller stomped on it, the next tick puts it back. Flux does not need a separate "self-heal" switch, because re-applying *is* the loop. Interval also bounds your worst-case delivery latency when you rely on polling. The `GitRepository` has its own interval for fetching; a commit is not visible to the Kustomization until the source picks it up. Total lag is roughly source interval plus reconcile time. Teams that want seconds instead of minutes add a `Receiver` (notification-controller) so a Git webhook triggers reconciliation immediately, and keep the polling interval as the backstop. There is also `retryInterval`, which defaults to `interval` and governs how soon a *failed* reconciliation is retried. Shortening the main interval to speed up retries is a common but blunt fix; setting `retryInterval` is the targeted one. ## prune: the deletion policy Applying is easy; garbage collection is the hard half. Flux keeps an **inventory** — the set of object references it applied for this Kustomization, recorded in the resource's status. On each reconcile it diffs the newly built set against the inventory. Objects present in the inventory but absent from the build are candidates for deletion. `prune: true` deletes them. `prune: false` (the default) leaves them running. That default surprises people, and it is why so many long-lived clusters carry orphans: a Deployment whose manifest was removed from Git two years ago is still serving traffic, invisible in the repo, unowned, un-upgraded, and quietly consuming quota. The whole premise of GitOps — the repository is the description of the system — is broken the moment removals do not propagate. Deleting the `Kustomization` object itself also triggers pruning of its inventory when prune is enabled, which is how you decommission a whole tenant cleanly. ## The symmetric hazard Pruning is powerful because it acts on absence, and absence is easy to produce by accident: - A typo in `path` points at a directory that builds to almost nothing. - A kustomize edit drops a resource from `resources:` unintentionally. - A `postBuild` substitution failure or a bad patch changes what is generated. - Someone re-scopes the Kustomization and the inventory no longer matches. Each of these looks to the controller exactly like "the operator removed these objects", and with prune on, they get deleted. Mitigations that experienced teams use: keep stateful and irreplaceable resources (PVCs, namespaces holding data, cluster-scoped one-offs) in a separate Kustomization with different blast radius; review with `flux diff kustomization <name> --path=./` before merging structural changes; use `flux suspend kustomization <name>` while doing risky refactors; and treat a build error as a hard stop — Flux does not prune when the build fails, precisely because an empty build must not read as an empty desired state. ## Related fields worth knowing - `suspend: true` stops reconciliation entirely for that object; the CLI equivalents are `flux suspend`/`flux resume`. - `wait: true` makes the reconciliation wait for all applied objects to become ready before reporting success. - `force: true` re-creates immutable resources on conflict instead of erroring — sharp, and rarely what you want by default. ## The short version for an interview Interval is how often the desired state is re-asserted, and is why drift heals without anyone acting. Prune is whether removal in Git means removal in the cluster; without it Git is only additive, and with it you must be careful that "nothing built" can never be mistaken for "nothing wanted".

  • Setting a very short interval on every Kustomization sounds safer. What does it cost?
    Every tick rebuilds the manifests and issues server-side applies for the whole inventory, so a fleet of short-interval Kustomizations multiplies API server request load and controller CPU. It also does not actually reduce delivery latency much, since the source's own fetch interval still gates new commits. Use a webhook Receiver for speed and keep intervals modest.
  • What stops Flux from pruning everything when a kustomize build fails?
    A failed build is a failed reconciliation: the controller reports the error on the Ready condition and does not compute a new applied set, so nothing is pruned. Pruning only diffs against a successfully built output. That is deliberate — an errored build must never be read as an empty desired state.
  • How would you decommission an entire tenant that Flux manages?
    Delete the tenant's Kustomization object while `prune: true` is set: Flux garbage-collects everything in that Kustomization's inventory. Removing the manifests from Git and letting the parent Kustomization prune the child achieves the same thing declaratively, which is usually preferred because the change is reviewable.

saying these in an interview costs you the question

  • Assumes prune is on by default
  • Thinks Flux only reconciles when a commit lands
  • Believes deleting a manifest from Git always removes the object
  • Says shortening interval is the way to reduce delivery latency
  • Expects a failed build to prune the whole inventory

context