Understanding ArgoCD Sync Policies and Options
In an enterprise GitOps workflow, the core objective is to ensure that the actual state of your Kubernetes clusters perfectly mirrors the desired state defined in your Git repositories. However, a simple "make it match" directive is rarely sufficient for production environments. Real-world deployments involve complex database migrations, high-availability state transitions, third-party mutating admission webhooks, horizontal pod autoscalers, and large custom resources that exceed traditional Kubernetes API limits.
To manage these complexities safely, ArgoCD provides a highly configurable set of Sync Policies and Sync Options. These settings dictate exactly how, when, and with what guardrails the ArgoCD Application Controller reconciles state differences.
This guide provides an exhaustive, production-grade deep dive into ArgoCD Sync Policies and Options. You will learn the underlying system architecture of the ArgoCD reconciliation engine, how to configure automated and manual sync behaviors, how to leverage advanced options like Server-Side Apply and Prune Last, and how to troubleshoot real-world sync failures and infinite sync loops.
What is an ArgoCD Sync Policy?
An ArgoCD Sync Policy defines whether synchronization between Git (the source of truth) and Kubernetes (the live state) occurs automatically or requires manual intervention. It is configured within the spec.syncPolicy block of an ArgoCD Application resource.
By pairing a Sync Policy with specific Sync Options (such as ServerSideApply, PruneLast, and RespectIgnoreDifferences), platform engineers can control:
- Whether resources not present in Git are deleted (Pruning).
- Whether manual drift in the cluster is automatically reverted (Self-Healing).
- How the Kubernetes API server processes resource manifests (e.g., Client-Side vs. Server-Side patching).
What You Will Learn
- The internal mechanics of the ArgoCD Application Controller reconciliation loop.
- How to configure and secure Automated Sync, Pruning, and Self-Healing.
- Deep technical analysis of all major ArgoCD Sync Options with production YAML manifests.
- How to handle edge cases like Mutating Webhooks, Horizontal Pod Autoscalers (HPA), and massive Custom Resource Definitions (CRDs).
- Enterprise-grade patterns for multi-tenant and multi-environment sync strategies.
- Step-by-step troubleshooting workflows for broken sync states and infinite reconciliation loops.
Prerequisites
To get the most out of this masterclass lesson, you should have:
- A solid understanding of basic Kubernetes resources (Deployments, Services, Namespaces, CRDs).
- Familiarity with GitOps principles (declarative configuration, version-controlled state).
- Access to a running Kubernetes cluster and a basic installation of ArgoCD. If you are new to these concepts, we highly recommend reading our Introduction to GitOps and ArgoCD Architecture Deep Dive first.
The ArgoCD Reconciliation Loop Architecture
Before configuring sync policies, it is crucial to understand how the ArgoCD Application Controller calculates state differences. ArgoCD does not simply run a continuous kubectl apply. Instead, it runs a highly optimized, event-driven reconciliation loop.
+------------------+ +----------------------+ +----------------------+
| Git Repository | | ArgoCD Repo Server | | Kubernetes Cluster |
| | | | | |
| (Desired State) | | (Generates Manifests)| | (Live State) |
+--------+---------+ +----------+-----------+ +----------+-----------+
| | |
| Pushes Commit | |
+--------------------------------->+ |
| | |
| | Fetches manifests |
| | |
| +----------v-----------+ |
| | ArgoCD Application | |
| | Controller | |
| | | |
| | 1. Compares States | |
| | 2. Detects Drift | |
| | 3. Applies Policies | |
| +----------+-----------+ |
| | |
| | If Out of Sync / Auto-Sync Enabled |
| +----------------------------------->+
| | Applies manifests using specified |
| | Sync Options & Hooks |
The reconciliation loop operates via the following distinct phases:
-
Manifest Generation: The
argocd-repo-serverpulls the target Git revision and renders the raw Kubernetes manifests (using Kustomize, Helm, Jsonnet, or raw YAML). -
State Caching: The
argocd-application-controllermaintains a local cache of the live cluster state by watching the Kubernetes API server's event stream. This minimizes direct API queries and prevents rate-limiting on large clusters. - Three-Way Diffing: The controller compares the Desired State (from Git), the Live State (from the cluster cache), and the Last Applied State (stored in the resource annotations). This three-way diff helps determine if a resource has drifted due to manual changes, controller mutations, or Git updates.
-
Sync Action Determination: Based on the comparison, the application is marked as
SyncedorOutOfSync. IfOutOfSyncand automated policies are enabled, the controller initiates a sync phase, applying resources in order of their configured Sync Waves and Hooks.
Manual vs. Automated Sync Policies
The first and most fundamental decision when defining an ArgoCD application is choosing between manual and automated synchronization.
Manual Sync Policy
When an application is configured with a manual sync policy, ArgoCD will detect drift and mark the application as OutOfSync, but it will never take action to modify the live cluster state until a human operator triggers a sync via the ArgoCD UI, CLI, or API.
Manual sync is highly recommended for:
- Production Environments: Where deployments must align with maintenance windows, undergo manual sanity checks, or coordinate with external systems.
- Stateful Applications: Such as databases, message queues, or storage engines where unexpected restarts or migrations could lead to data corruption or service degradation.
- Complex Upgrades: Multi-step migrations where a platform engineer needs to closely monitor logs and metrics between resource updates.
Automated Sync Policy
Automated sync instructs the ArgoCD Application Controller to immediately apply changes to the live cluster as soon as a difference between Git and the cluster is detected.
Automated sync is highly recommended for:
- Development and Staging Environments: To enable rapid feedback loops for developers. Changes merged to the main branch are immediately reflected in the cluster.
- Stateless Microservices: Applications with robust health checks and rolling update strategies that can safely deploy continuously without human oversight.
- Platform Configurations: Core infrastructure tools (like external-dns, cert-manager, or ingress controllers) that should always match their Git definitions without manual step blockages.
Here is a standard declaration of an Application utilizing an automated sync policy:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook-dev
namespace: argocd
spec:
project: default
source:
repoURL: 'https://github.com/argoproj/argocd-example-apps.git'
targetRevision: HEAD
path: guestbook
destination:
server: 'https://kubernetes.default.svc'
namespace: guestbook
syncPolicy:
automated:
prune: false
selfHeal: false
The Twin Pillars: Pruning and Self-Healing
When you enable automated sync, you must configure two critical sub-behaviors: Pruning and Self-Healing. Understanding the interaction between these two settings is vital to preventing accidental data loss or deployment gridlocks.
1. Prune (Deletion of Extraneous Resources)
By default, if you delete a resource manifest from your Git repository, ArgoCD will not delete the corresponding resource from your Kubernetes cluster. It will simply stop tracking it. This is a safety mechanism designed to prevent accidental deletions of critical resources.
By setting prune: true, you instruct ArgoCD to actively delete any resources in the cluster that are managed by this Application but are no longer defined in the Git repository.
prune: true without proper safeguards can be highly destructive. For example, if a developer accidentally deletes a PersistentVolumeClaim or a Namespace manifest from Git, ArgoCD will immediately delete those live resources, potentially causing permanent data loss. Always combine pruning with robust branch protection rules and peer reviews in Git.
2. Self-Heal (Reverting Cluster Drift)
Kubernetes resources can drift from their Git definitions due to manual changes (e.g., an engineer running kubectl edit deployment during an incident) or external controllers.
If selfHeal: false, ArgoCD will detect this drift, mark the resource as OutOfSync, but will not modify it.
If selfHeal: true, ArgoCD will actively overwrite any manual changes in the cluster with the desired state defined in Git. The controller detects the drift and immediately issues a patch to the Kubernetes API server to restore the Git-defined state.
Prune and Self-Heal Matrix
| Scenario | Prune: False / Self-Heal: False | Prune: True / Self-Heal: False | Prune: True / Self-Heal: True |
|---|---|---|---|
| Resource deleted from Git | Resource remains in cluster. App marked OutOfSync. | Resource is deleted from cluster immediately. | Resource is deleted from cluster immediately. |
| Manual change in cluster (Drift) | Drift remains. App marked OutOfSync. | Drift remains. App marked OutOfSync. | ArgoCD overwrites drift with Git state. |
| New resource added to Git | Resource is created in cluster. | Resource is created in cluster. | Resource is created in cluster. |
Exhaustive Breakdown of ArgoCD Sync Options
While Sync Policies define the *macro* behavior (manual vs. auto), Sync Options allow platform engineers to tune the *micro* behavior of how individual manifests are parsed, validated, and applied. Sync options are configured as a list of strings within the spec.syncPolicy.syncOptions block.
1. CreateNamespace=true
By default, if the destination namespace specified in the Application manifest does not exist in the target cluster, the sync will fail. Enabling CreateNamespace=true instructs ArgoCD to automatically create the namespace before applying any other resources.
Production Warning: If you rely on namespace-level annotations/labels for service meshes (e.g., Istio sidecar injection labels) or network policies, creating namespaces automatically this way will create them without those labels unless you configure default namespace templates. It is generally safer in enterprise environments to declare Namespace resources explicitly in Git.
2. ServerSideApply=true
By default, ArgoCD uses client-side apply (equivalent to kubectl apply). This generates a large kubectl.kubernetes.io/last-applied-configuration annotation on the resource. However, Kubernetes annotations have a size limit of 262KB. Large resources, such as complex Custom Resource Definitions (CRDs) or large ConfigMaps, will fail to sync with an annotation size exceeded error.
Enabling ServerSideApply=true bypasses the client-side annotation limit by offloading the merge logic to the Kubernetes API server itself. It tracks field ownership using metadata.managedFields, completely eliminating the annotation size issue.
3. ApplyOutOfSyncOnly=true
In large applications containing hundreds of resources, a sync operation can place significant load on the Kubernetes API server as ArgoCD attempts to apply every single resource manifest.
Setting ApplyOutOfSyncOnly=true optimizes this process. ArgoCD will scan the diff and only apply the specific resources that are currently marked as OutOfSync. Resources that already match their Git definitions are skipped, drastically reducing API overhead and execution times.
4. Replace=true
Some Kubernetes resources contain immutable fields that cannot be updated via standard strategic merge patches. For example, modifying the spec.selectors of a Deployment or certain fields of a Job will result in a validation error from the API server.
By default, ArgoCD will fail the sync when encountering these immutable changes. If you enable Replace=true, ArgoCD will perform a destructive update: it will execute a kubectl replace or kubectl delete followed by a kubectl create for that specific resource.
Operational Risk: This option can cause temporary service disruption because it deletes the old resource before creating the new one. Use with caution on critical path workloads.
5. PruneLast=true
During a sync operation that involves both creating new resources and pruning old ones, ArgoCD's default behavior is to execute pruning *first*. This can lead to service degradation. For example, if you are renaming a service or shifting traffic, pruning the old service before the new one is fully healthy can cause traffic drops.
Setting PruneLast=true forces ArgoCD to apply all new and updated resources first, wait for them to become healthy, and only then perform the pruning of the obsolete resources.
6. FailOnSharedResource=true
In multi-tenant clusters, different teams might accidentally declare the same resource (e.g., the same Ingress host or the same ConfigMap in a shared namespace) in their respective Git repositories.
By default, ArgoCD will allow the second application to overwrite the resource created by the first application. This is called "resource hijacking."
Enabling FailOnSharedResource=true prevents this. If ArgoCD attempts to sync a resource that is already managed by another Application, the sync will fail immediately, protecting the original owner's state.
7. RespectIgnoreDifferences=true
ArgoCD allows you to configure ignoreDifferences to ignore specific fields (such as replica counts managed by HPAs or dynamic inject annotations from cloud providers). However, during manual or automated syncs, ArgoCD may still attempt to apply those fields if they are explicitly defined in Git.
Setting RespectIgnoreDifferences=true ensures that even during a sync operation, ArgoCD will completely strip out the ignored fields from the manifest before applying them, preserving the live state of those specific fields.
8. PrunePropagationPolicy
When pruning resources, ArgoCD must tell the Kubernetes API server how to handle dependent child resources. This is configured using the PrunePropagationPolicy option, which maps directly to Kubernetes garbage collection policies:
PrunePropagationPolicy=foreground: Child resources are deleted first, and only when they are gone is the parent resource deleted. (Safest for ensuring clean teardowns).PrunePropagationPolicy=background: The parent resource is deleted immediately, and the Kubernetes garbage collector cleans up the orphaned child resources in the background. (Default behavior).PrunePropagationPolicy=orphan: The parent resource is deleted, but its child resources are left running in the cluster, unmanaged.
Step-by-Step Enterprise Implementation Guide
Let's look at a production-ready ArgoCD Application manifest that implements these advanced sync options for a high-scale, multi-tenant microservice deployment.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: payment-gateway-prod
namespace: argocd
labels:
tier: backend
environment: production
spec:
project: core-payments
source:
repoURL: 'https://github.com/enterprise-org/payment-gitops.git'
targetRevision: tags/v2.4.1
path: environments/production/payment-gateway
helm:
valueFiles:
- values.yaml
- values-prod.yaml
destination:
server: 'https://prod-k8s-cluster.internal'
namespace: payments
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
# Automatically create the payments namespace if missing
- CreateNamespace=true
# Use Server-Side Apply to accommodate massive CRDs/ConfigMaps
- ServerSideApply=true
# Optimize performance by only applying drifted resources
- ApplyOutOfSyncOnly=true
# Ensure new pods are healthy before pruning old configurations
- PruneLast=true
# Prevent other teams from hijacking our resources
- FailOnSharedResource=true
# Always honor ignored fields (like HPA replica modifications)
- RespectIgnoreDifferences=true
# Use foreground deletion to ensure clean cleanup of dependencies
- PrunePropagationPolicy=foreground
retry:
limit: 5 # Number of failed sync attempts to retry
backoff:
duration: 5s # Initial delay before retrying
factor: 2 # Multiply delay by this factor on subsequent failures
maxDuration: 3m0s # Maximum delay limit
This manifest sets up a highly resilient, self-healing sync loop. If a network blip occurs or a dependency is temporarily unavailable, the retry block ensures that ArgoCD will back off and try again rather than immediately failing the deployment pipeline.
Avoiding the Dreaded Sync Loop
One of the most common operational failures in automated GitOps environments is the Infinite Sync Loop. This occurs when an application is permanently stuck in an OutOfSync state, continuously applying changes, only to immediately drift again.
The Anatomy of a Sync Loop
Sync loops are almost always caused by a conflict between ArgoCD's desired state and an in-cluster mutating controller or admission webhook.
+-----------------------------------------------------------------------+
| The Sync Loop Cycle |
| |
| 1. ArgoCD applies Manifest (Git State: replicaCount=3) |
| | |
| v |
| 2. Kubernetes Mutating Webhook intercepts request |
| and alters field (e.g., injects sidecar, sets replicaCount=1) |
| | |
| v |
| 3. Live State in etcd now differs from Git State |
| | |
| v |
| 4. ArgoCD detects drift (Status: OutOfSync) |
| | |
| v |
| 5. Because Self-Heal is enabled, ArgoCD immediately re-applies Git |
| (Loop restarts at Step 1, creating continuous CPU/API churn) |
+-----------------------------------------------------------------------+
Common Culprits
- Horizontal Pod Autoscalers (HPA): The HPA controller dynamically updates the
spec.replicasfield of a Deployment based on CPU load. If your Git manifest explicitly declaresreplicas: 3, ArgoCD will continuously attempt to scale it back to 3, while the HPA attempts to scale it to 10. - Vault Agent Injectors / Istio Sidecars: These tools mutate pod templates by injecting sidecar containers, environment variables, or volume mounts. If ArgoCD compares the entire pod template strictly, it will detect these injections as drift.
- Service Account Tokens: Kubernetes automatically populates token secrets and mounts them.
How to Fix Sync Loops Using ignoreDifferences
To resolve sync loops, you must instruct ArgoCD to ignore the specific fields that are mutated by external controllers. This is configured in the spec.ignoreDifferences block of the Application manifest.
Here is how to configure an Application to ignore HPA replica changes and Istio sidecar injection modifications:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: payment-gateway-prod
namespace: argocd
spec:
# ... source and destination config ...
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- RespectIgnoreDifferences=true
ignoreDifferences:
# Ignore HPA scaling changes on our Deployment
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
# Ignore Istio injection labels and annotations added dynamically
- group: ""
kind: Pod
jsonPointers:
- /metadata/labels/security.istio.io~1tlsMode
- /metadata/annotations/prometheus.io~1scrape
Pro-Tip: Notice the use of ~1 in the JSON pointer path. Because JSON pointers use / as a separator, any literal forward slash in a label or annotation key (like security.istio.io/tlsMode) must be escaped as ~1.
Observability, Metrics, and Monitoring Sync States
In enterprise deployments, you cannot rely solely on the ArgoCD dashboard to know if your applications are syncing correctly. You must integrate ArgoCD metrics with your central monitoring stack (e.g., Prometheus and Grafana).
The argocd-application-controller exports standard Prometheus metrics on port 8082.
Key Prometheus Metrics to Alert On
-
argocd_app_info: Provides metadata about the application, including its health status (Healthy,Degraded) and sync status (Synced,OutOfSync).
Alerting Query (App Out of Sync for > 15m):argocd_app_info{sync_status="OutOfSync"} == 1 -
argocd_app_sync_total: A counter tracking the total number of sync operations. A rapid spike in this counter indicates an active, runaway sync loop.
Alerting Query (High Sync Frequency):rate(argocd_app_sync_total[5m]) > 0.1 -
argocd_app_reconcile_count: Tracks the total number of application reconciliation operations.
Configuring Prometheus ServiceMonitor
To scrape these metrics using the Prometheus Operator, deploy the following ServiceMonitor:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: argocd-metrics
namespace: argocd
spec:
selector:
matchLabels:
app.kubernetes.io/name: argocd-application-controller
endpoints:
- port: metrics
interval: 30s
Troubleshooting and Debugging Sync Failures
When an application sync fails or hangs, follow this structured debugging workflow to isolate and remediate the issue.
Step 1: Inspect the Application Resource via CLI
Often, the quickest way to find the root cause of a sync failure is to describe the Application resource using kubectl or the argocd CLI.
# Using kubectl to inspect the status and events
kubectl describe app payment-gateway-prod -n argocd
# Using the ArgoCD CLI to view sync details
argocd app get payment-gateway-prod
Look closely at the Status.Conditions and Status.Sync.Result fields. This is where Kubernetes API validation errors (e.g., missing CRDs, invalid fields, or RBAC permission denials) are surfaced.
Step 2: Check the Application Controller Logs
If the UI or CLI is unresponsive or shows generic errors, check the raw logs of the controller pod.
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller --tail=100 -f
Look for errors containing failed to sync, permission denied, or webhook mutation conflict.
Step 3: Handle Common Sync Error Scenarios
Scenario A: "Namespace not found"
Symptom: The sync fails immediately stating the target namespace does not exist.
Fix: Add the CreateNamespace=true sync option to your application, or explicitly define the Namespace resource in your Git repository.
Scenario B: "CustomResourceDefinition ... not found"
Symptom: You are deploying a Custom Resource (CR) and its corresponding Custom Resource Definition (CRD) in the same sync, and the sync fails because the API server does not recognize the CR.
Fix: By default, ArgoCD attempts to apply CRDs first. However, if the API server takes a few seconds to register the CRD, the subsequent application of the CR will fail. Ensure you do not have SkipDryRunOnMissingResource=true configured unwisely, and consider placing CRDs in a separate Git directory managed by Sync Waves (e.g., Wave -1) so they are fully established before the CRs are applied.
Scenario C: "Request entity too large" or "annotation size exceeded"
Symptom: Sync fails on large ConfigMaps, Secrets, or CRDs.
Fix: Add the ServerSideApply=true sync option to bypass the client-side annotation size limit.
Enterprise Security & Governance with Sync Policies
Enabling automated synchronization, pruning, and namespace creation introduces potential security vectors that enterprise platform teams must govern.
1. Enforcing RBAC on Namespace Creation
If you allow developers to configure CreateNamespace=true, they can theoretically deploy applications to any namespace in the cluster, potentially bypassing network security policies or hijacking namespaces reserved for system utilities.
Remediation: Use ArgoCD Projects (AppProjects) to restrict the namespaces that an application can target. Even if CreateNamespace=true is set, ArgoCD will block the sync if the targeted namespace is not explicitly permitted in the AppProject definition.
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: payment-team
namespace: argocd
spec:
description: "Restricted project for the payment gateway team"
# Only allow deployments to namespaces starting with 'payments-'
destinations:
- namespace: 'payments-*'
server: 'https://kubernetes.default.svc'
2. Auditing Git Commits
Because automated sync immediately applies any changes merged to the tracked Git branch, your Git repository becomes the security perimeter. If a malicious actor gains write access to your repository, they can commit a malicious deployment (e.g., a privileged pod or cluster-admin ClusterRoleBinding) which ArgoCD will instantly sync.
Remediation:
- Enforce branch protection rules on your production branches requiring signed commits, mandatory code reviews (PRs), and successful CI/CD checks.
- Configure ArgoCD to only sync to signed commits or specific release tags (e.g.,
targetRevision: tags/v2.4.1) rather than tracking a mutable branch likemainormaster.
Technical Interview Questions & Answers
Q1: What is the difference between Client-Side Apply and Server-Side Apply in ArgoCD? When should you use Server-Side Apply?
Answer: Client-Side Apply is the traditional method where ArgoCD calculates differences locally and sends a patch request containing the kubectl.kubernetes.io/last-applied-configuration annotation. This annotation has a strict size limit of 262KB.
Server-Side Apply offloads the diff and merge calculations to the Kubernetes API server itself. It tracks field ownership using metadata.managedFields instead of annotations, thus eliminating the 262KB size limit. You should use Server-Side Apply for large ConfigMaps, complex Custom Resource Definitions (CRDs), or when multiple controllers need to manage different fields of the same resource.
Q2: How does ArgoCD handle resources that are deleted from Git when automated sync is enabled?
Answer: By default, ArgoCD will *not* delete those resources from the cluster. It simply marks the application as OutOfSync and stops tracking them. To force deletion of resources removed from Git, you must explicitly enable the prune option (prune: true) within the application's automated sync policy.
Q3: What is the purpose of the PruneLast=true sync option? Give a real-world scenario where it is useful.
Answer:
PruneLast=true instructs ArgoCD to perform resource pruning *after* all new and updated resources have been applied and have reached a healthy state.
A real-world scenario is when you are migrating an application from an old Deployment and Service to a new Deployment and Service with different names. If you prune first (default behavior), the old Service is deleted immediately, causing a traffic drop before the new Service is up and ready. Using PruneLast=true ensures the new Service is live and routing traffic before the old one is safely cleaned up.
Q4: How would you resolve an infinite sync loop caused by a Horizontal Pod Autoscaler (HPA) modifying replicas?
Answer: You must configure spec.ignoreDifferences in the Application manifest to ignore the /spec/replicas path for the targeted Deployment. Additionally, you should enable the RespectIgnoreDifferences=true sync option to ensure ArgoCD does not attempt to apply the replica count defined in Git during automated sync executions.
Q5: What does the FailOnSharedResource=true option protect against?
Answer: It protects against "resource hijacking" in multi-tenant clusters. If team A has already deployed a resource (e.g., an Ingress) using ArgoCD, and team B attempts to declare the same resource in their Git repository, enabling this option will cause team B's sync to fail, preventing them from accidentally overwriting or hijacking team A's resource.
Frequently Asked Questions
Can I use automated sync in production safely?
Yes, but it requires strict guardrails. You should combine automated sync with robust branch protection in Git (requiring pull request approvals), enable PruneLast=true to prevent premature deletions, configure RespectIgnoreDifferences=true to prevent conflicts with autoscalers, and use ArgoCD AppProjects to restrict namespace access.
Why did my sync fail with "annotation size exceeded"?
This occurs because the resource (usually a CRD or ConfigMap) is larger than 262KB, which exceeds the limit of the kubectl.kubernetes.io/last-applied-configuration annotation used by client-side apply. To fix this, add ServerSideApply=true to your Application's syncOptions.
How often does ArgoCD check Git for changes?
By default, ArgoCD polls Git repositories every 3 minutes. However, you can configure Webhooks (such as GitHub, GitLab, or Bitbucket webhooks) to notify ArgoCD instantly when a commit is pushed, reducing the sync delay to seconds.
What is the difference between selfHeal: true and a standard Kubernetes reconciliation loop?
A standard Kubernetes reconciliation loop (like the Deployment controller) ensures that the live state matches the desired state *stored in the cluster's etcd*. ArgoCD's selfHeal: true ensures that the state stored in etcd matches the desired state *stored in your Git repository*. It bridges the gap between external version control and the cluster API.
What happens if a sync fails halfway through? Does ArgoCD roll back?
ArgoCD does not automatically "roll back" to a previous Git commit if a sync fails. It will attempt to retry the sync according to your configured retry backoff policy. If the sync cannot be completed (e.g., due to an invalid manifest), the application will remain in a Degraded or OutOfSync state. To roll back, you must revert the commit in Git, and ArgoCD will sync the reverted state.
Can I apply sync options to individual resources instead of the entire Application?
Yes. You can apply specific sync options as annotations directly on individual resource manifests within your Git repository. For example, to force Server-Side Apply on a single CRD, you can add the annotation argocd.argoproj.io/sync-options: ServerSideApply=true to that specific manifest.
Summary & Best Practices
Mastering ArgoCD Sync Policies and Options is critical to running safe, predictable GitOps pipelines at scale. Here are the key takeaways from this masterclass lesson:
- Dev vs. Prod: Use Automated Sync with Self-Heal and Pruning in development/staging for rapid iteration. Use Manual Sync (or automated sync with highly strict branch protections) in production to maintain operational control.
- Always use ServerSideApply: Enable