Argo CD Synchronization Strategies: Automated, Manual, and Progressive Sync Explained
Argo CD supports manual, automated, and progressive synchronization strategies that control how Git-tracked desired state is applied to Kubernetes clusters through the SyncPolicy object in Application and ApplicationSet manifests.
Argo CD, the declarative GitOps continuous delivery tool for Kubernetes, reconciles the live state of your cluster with the desired state defined in Git. Understanding the available Argo CD synchronization strategies is essential for safely deploying applications at scale while controlling blast radius and automating drift correction. This guide examines the implementation details in the argoproj/argo-cd repository to explain how automated sync, sync options, retry logic, and progressive rollouts work under the hood.
Automated Synchronization
When you configure an Application with spec.syncPolicy.automated, Argo CD continuously reconciles the live cluster state to match the target Git revision. The automation logic resides in pkg/apis/application/v1alpha1/types.go, where the IsAutomatedSyncEnabled method (lines 1518–1536) checks whether continuous reconciliation should run.
The SyncPolicyAutomated struct (lines 1608–1616) defines four boolean fields that tune the behavior:
prune– Deletes resources that exist in the cluster but no longer appear in the Git source (default:false).selfHeal– Re-applies manifests when live resources drift from the desired state (default:false).allowEmpty– Permits an application to have zero live resources without triggering an error (default:false).enabled– Explicit on/off switch for automation; defaults totrueif omitted.
Sync Options and Retry Configuration
Beyond the automation flags, the SyncPolicy object accepts two additional tuning mechanisms defined in pkg/apis/application/v1alpha1/types.go.
Sync options are a list of key=value strings stored in SyncPolicy.SyncOptions (lines 1521–1523). These influence the underlying kubectl execution or resource hooks, such as CreateNamespace=true or Prune=true.
Retry strategy (SyncPolicy.Retry, lines 1543–1660) configures how failed syncs are retried. The RetryStrategy struct includes:
limit– Maximum number of retry attempts.backoff– Containsduration(initial wait),factor(exponential multiplier), andmaxDuration(upper cap).refresh– Boolean flag that triggers a re-fetch of the latest Git revision before each retry attempt.
The NextRetryAt helper method calculates the next scheduled retry based on the backoff configuration.
Progressive (Rolling) Synchronization
Argo CD supports progressive (or rolling) syncs, an experimental feature that applies changes to subsets of applications in controlled waves. This strategy is managed by the ApplicationSet controller and must be enabled with the --enable-progressive-syncs flag in cmd/argocd-applicationset-controller/commands/applicationset_controller.go (lines 311–319).
When active, the controller watches ApplicationSet.Spec.SyncPolicy for a RollingSync strategy and advances applications through defined steps based on their health status.
Progressive Sync Status Tracking
Each application in a progressive sync carries a ProgressiveSyncStatusCode defined in pkg/apis/application/v1alpha1/applicationset_types.go (lines 890–904). The status transitions through the following states:
Waiting– Application is queued for the next wave.Pending– Application is selected for the current wave but not yet updated.Progressing– Sync is actively running.Healthy– Application has reached the target state and passed health checks.
The Progressive Sync Manager
The wave logic is implemented in applicationset/progressivesync/progressive_sync.go. The Manager.PerformProgressiveSyncs method (lines 77–110) evaluates the RollingSync steps, which contain selectors (e.g., label selectors) and maxUpdate limits defining how many applications can update simultaneously. The manager updates each application's ProgressiveSyncStatusCode as the rollout proceeds through the configured steps.
Manual Synchronization
If spec.syncPolicy is omitted or Automated.enabled is explicitly set to false, Argo CD operates in manual mode. In this mode, synchronization only occurs when explicitly triggered via the UI, CLI, or API. The same SyncPolicy fields for options and retry logic still apply to these one-off operations, allowing you to configure CreateNamespace behavior or retry limits even for manual syncs.
How the Reconcile Loop Evaluates Sync Policies
During the normal reconciliation loop in server/application/application.go (lines 2109–2126), Argo CD checks the automation flag before invoking the sync engine:
if a.Spec.SyncPolicy != nil && a.Spec.SyncPolicy.IsAutomatedSyncEnabled() && !syncReq.GetDryRun() {
// trigger automated sync
}
This conditional ensures that automated syncs are skipped during dry-run requests and respects the enabled field defined in the SyncPolicyAutomated configuration. When progressive sync is active, the ApplicationSet controller invokes the progressive sync manager instead of the standard application-level sync logic.
Configuration Examples
Simple Automated Sync
The following Application manifest enables continuous reconciliation with resource pruning and self-healing:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: guestbook
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps
targetRevision: HEAD
path: guestbook
destination:
server: https://kubernetes.default.svc
namespace: guestbook
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Retry Strategy Configuration
Add exponential backoff to handle transient failures during sync operations:
spec:
syncPolicy:
automated: {}
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 1m
refresh: true
Progressive Sync with ApplicationSet
Configure rolling updates across clusters with wave-based selectors:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: rolling-sync-demo
spec:
generators:
- list:
elements:
- cluster: cluster-a
- cluster: cluster-b
template:
metadata:
name: '{{cluster}}-guestbook'
spec:
project: default
source:
repoURL: https://github.com/argoproj/argocd-example-apps
path: guestbook
targetRevision: HEAD
destination:
server: https://{{cluster}}.k8s.example.com
namespace: guestbook
syncPolicy:
rollingSync:
steps:
- selector:
matchLabels:
tier: frontend
maxUpdate: 1
- selector:
matchLabels:
tier: backend
maxUpdate: 2
Manual Sync Trigger via CLI
Trigger a one-off sync with specific options even when automation is disabled:
argocd app sync guestbook \
--prune \
--retry-limit 3 \
--sync-option CreateNamespace=true
Summary
- Automated sync is controlled by the
SyncPolicyAutomatedstruct inpkg/apis/application/v1alpha1/types.goand evaluated byIsAutomatedSyncEnabled()before each reconciliation. - Sync options and retry strategies allow fine-grained control over namespace creation, pruning behavior, and exponential backoff during failed syncs.
- Progressive sync enables wave-based rollouts through the
ApplicationSetcontroller, usingProgressiveSyncStatusCodestates and thePerformProgressiveSyncsmanager inapplicationset/progressivesync/progressive_sync.go. - Manual sync relies on user-initiated triggers but can still leverage the same
SyncPolicyoptions for pruning and retries. - The core reconcile loop in
server/application/application.gogates automated execution based on theSyncPolicyconfiguration and dry-run status.
Frequently Asked Questions
What is the difference between automated and manual sync in Argo CD?
Automated sync continuously reconciles the cluster state with Git whenever drift is detected or the target revision changes, while manual sync only executes when explicitly triggered by a user or external API call. According to the source code in pkg/apis/application/v1alpha1/types.go, automated sync requires the SyncPolicy.Automated block to be present and enabled, which the controller checks via IsAutomatedSyncEnabled() before initiating the sync engine.
How does Argo CD handle sync failures with the retry strategy?
Argo CD implements exponential backoff for failed syncs through the RetryStrategy struct defined in pkg/apis/application/v1alpha1/types.go. You can configure the limit (maximum attempts), backoff.duration (initial delay), backoff.factor (multiplier), and backoff.maxDuration (cap). The refresh flag optionally re-fetches the latest Git revision before each retry attempt, and the NextRetryAt method calculates the precise timing for the next attempt.
What is progressive sync and when should I use it?
Progressive sync is an experimental Argo CD feature that performs rolling updates across multiple applications in controlled waves, managed by the ApplicationSet controller. It is useful for canary deployments or multi-cluster rollouts where you want to limit blast radius by updating only a subset of applications (maxUpdate) at a time. The feature requires enabling the --enable-progressive-syncs flag and defines steps with label selectors in spec.syncPolicy.rollingSync.
Can I use sync options like CreateNamespace without enabling automated sync?
Yes. Sync options defined in SyncPolicy.SyncOptions (such as CreateNamespace=true) apply to both automated and manual synchronizations. When using the CLI, you can pass these options via --sync-option flags, and they will be respected regardless of whether spec.syncPolicy.automated is configured in your Application manifest.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →