Git, CI/CD & GitOpsLXXIX · Sync StrategiesSyncStrategies
Prune and the blast radius — what prune deletes and the safety discipline
What you'll learn
- Describe what prune deletes and what it does not
- Identify the failure mode an unintended prune produces in production
- Configure prune per-Application using --auto-prune and the Prune=false sync option
- Apply the safety discipline - namespace backup, ownership audit, dry-run - before enabling prune
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
Prune is the option that makes “delete this from the cluster” a Git commit rather than a kubectl command. The commit lands, the controller reconciles, the resource is deleted from the cluster. The change is auditable; the deletion is reproducible. But the same property that makes prune an audit trail - it deletes unconditionally on a diff that removes the resource - is what makes an unintended prune catastrophic.
What prune actually deletes
Prune is enabled with spec.syncPolicy.automated.prune (the
--auto-prune flag) in Argo CD or spec.prune: true in Flux.
The controller’s contract:
- Prune deletes resources the controller owns. A resource present in the cluster but absent from the previous apply inventory is a candidate for deletion.
- Prune does not delete resources the controller does not own.
A
kubectl applyfrom an operator, a Helm install from another chart, a resource the controller has never seen are not pruned. Argo CD inventories its own resources by metadata; Flux inventories by thekustomize.toolkit.fluxcd.io/namelabel. - Prune follows the chart’s source. A manifest that is removed from the chart, or a values entry that resolves to an empty set, results in a prune of the corresponding resource.
argocd app set payment-api \
--auto-prune
The --auto-prune flag enables pruning when the chart loses a
manifest. The per-sync alternative is argocd app sync payment-api --prune, which prunes on one manual sync;
individual resources opt out with the
argocd.argoproj.io/sync-options: Prune=false annotation.
The blast radius of an unintended prune
A chart that loses a manifest because the manifest was moved
to a different chart, because the manifest was renamed, because
the values-merge produced an empty list - will, under
prune: true, delete the corresponding resource from the
cluster. The chart’s bug becomes the cluster’s outage.
flowchart LR
M["Manifest removed from chart"] --> R["Render omits resource"]
R --> D["Diff shows resource missing"]
D --> P{"prune=true?"}
P -->|yes| X["DELETE resource from cluster"]
P -->|no| W["Resource stays in cluster"]
X --> C["Cluster state matches Git"]
W --> C
The right side of the diagram is the production-grade failure
mode: the resource stays, the cluster drifts from Git, and the
Kustomization reports Ready=True anyway because its apply
contract only covers what is in the new build. The left side is
the catastrophic failure mode: the resource is deleted.
The safety discipline
Three rules that make prune survivable:
- Per-Application configuration. Prune is enabled per Application, not per cluster. A workload whose chart shares resources with another workload (an admission webhook shared with another Application, a ConfigMap referenced by both) must not have prune enabled until the ownership is clear.
- Namespace backup before first prune. The first time a chart with prune enabled deploys, the team must be able to restore the namespace if the prune deletes something unexpected. The backup is the recovery path; the audit is the prevention.
- Dry-run before prune. Argo CD’s
argocd app diff payment-apishows what the next sync will do. A team that enables prune should diff the next sync and confirm the deletions match the team’s intent.
The Prune=false sync option override
The escape hatch when an Application - or a single resource - must not be pruned, even with prune otherwise enabled:
argocd app set payment-api \
--sync-option Prune=false
This sets the Prune=false sync option on the Application’s
standing configuration. Syncs stop deleting its resources;
prune candidates are reported as out-of-sync instead. Remove
the option with argocd app set payment-api --sync-option '!Prune=false' (the ! prefix removes the option) to resume
pruning; the opt-out is standing and reversible, not permanent. For one resource, the same opt-out
is the argocd.argoproj.io/sync-options: Prune=false
annotation on the resource itself.
The same effect is achieved in Flux with spec.prune: false on
the Kustomization; in both controllers the opt-out is a
standing, reversible setting.
Prune in Flux versus Argo CD
The two controllers implement prune differently:
- Argo CD prunes any resource in the Application’s
inventory that is not in the new render. The app-level
Prune=falsesync option and the per-resourcePrune=falseannotation tune the boundary. - Flux prunes only resources it has the
kustomize.toolkit.fluxcd.io/namelabel on. A resource that was never applied by the controller is not pruned; a resource that was applied by the controller and is now absent from the build is pruned.
The Flux boundary is tighter by default. Argo CD’s boundary is broader by default and tunable with the app-level sync option and the per-resource annotation.
Production discipline
- Prune is enabled per Application after an ownership audit. The team must know what the controller will delete before the first prune-enabled sync.
- Prune is paired with a namespace backup. The first prune-enabled sync is the highest-risk deploy the team will ever do for that Application.
- Prune is paired with branch protection. A typo in the chart must not auto-prune before review.
Prune=falsesync option is the standing opt-out. Set it per-Application withargocd app set --sync-option Prune=false, or per-resource with theargocd.argoproj.io/sync-options: Prune=falseannotation.
Cross-course references
- Git, CI/CD & GitOps for Infrastructure Engineers - Part LXXVII-04 (Sync policies and windows) covers the policy frame this lesson deepens; Part LXXVI (GitOps Repo Architecture) is where the chart structure that prune operates on lives.
- Kubernetes for Production Sysadmins - Part VII (Workloads) is the resource class prune operates on; Part XVI (Operators and Controllers) covers the reconcile loop.
Quiz
Knowledge check · 4 questions
Q1. A team enables prune on an Application whose chart shares a ConfigMap with another Application. What is the most likely production failure?
Q2. Prune in Flux and Argo CD have the same default behaviour: both delete any cluster resource absent from the new render.
Q3. Name the three rules of the prune safety discipline and explain why each is necessary.
Q4. Diagnose why a critical ConfigMap was deleted and recommend the prevention.
A team runs an Application with prune enabled in production. A developer refactors a Helm chart and removes a ConfigMap that is also consumed by an admission controller in the same namespace. The PR is merged; the next automated sync prunes the ConfigMap. The admission controller fails to start its webhook server because the ConfigMap is missing, and production admission breaks. The team has no namespace backup. The ConfigMap is restored from an outdated commit that did not have the admission controller's CA bundle.
Passing score: 75%. Answers are checked in this browser.