Properly Configuring preserveResourcesOnDeletion in Argo CD ApplicationSets

Clarifying Where to Set preserveResourcesOnDeletion to Avoid Unintended Resource Deletions

When working with ApplicationSets in Argo CD, it's important to understand how to preserve Kubernetes resources after the deletion of the ApplicationSet. This is where the preserveResourcesOnDeletion: true setting comes in—but documentation can be unclear on where exactly this should be configured.

This article clarifies where and how to apply preserveResourcesOnDeletion to avoid confusion and unintended consequences.


Where to Set preserveResourcesOnDeletion

You do not set preserveResourcesOnDeletion directly in the top-level spec of the ApplicationSet.

Instead, you set it within the spec.template.spec.syncPolicy of the generated Application.

Here’s an example of how to do it correctly:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-appset
  namespace: argocd
spec:
  syncPolicy:
    applicationsSync: create-update
  generators:
    - list:
        elements:
          - cluster: dev
            url: https://dev-cluster
  template:
    metadata:
      name: '-myapp'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/repo
        targetRevision: HEAD
        path: apps/myapp
      destination:
        server: ''
        namespace: my-namespace
      syncPolicy:
        syncOptions:
          - CreateNamespace=true
          - PreserveResourcesOnDeletion=true  # <-- Correct placement

What This Setting Does:

preserveResourcesOnDeletion=true

Under syncPolicy.syncOptions ensures that resources created by Argo CD Applications are not deleted when the corresponding Application (generated from an AppSet) is deleted.

This is especially important for stateful or shared resources like PVCs, databases, or custom CRDs.

Important Notes

  • This is configured per Application, so it must be part of the template in an ApplicationSet.

  • It will not work if added to the top-level ApplicationSet.spec—it must be nested under template.spec.syncPolicy.syncOptions.