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 to true if 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 – Contains duration (initial wait), factor (exponential multiplier), and maxDuration (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 SyncPolicyAutomated struct in pkg/apis/application/v1alpha1/types.go and evaluated by IsAutomatedSyncEnabled() 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 ApplicationSet controller, using ProgressiveSyncStatusCode states and the PerformProgressiveSyncs manager in applicationset/progressivesync/progressive_sync.go.
  • Manual sync relies on user-initiated triggers but can still leverage the same SyncPolicy options for pruning and retries.
  • The core reconcile loop in server/application/application.go gates automated execution based on the SyncPolicy configuration 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →