# Argo CD Synchronization Strategies: Automated, Manual, and Progressive Sync Explained

> Master Argo CD synchronization strategies including automated, manual, and progressive sync. Learn how to effectively manage your Kubernetes cluster deployments with SyncPolicy.

- Repository: [Argo Project/argo-cd](https://github.com/argoproj/argo-cd)
- Tags: deep-dive
- Published: 2026-07-14

---

**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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/server/application/application.go) (lines 2109–2126), Argo CD checks the automation flag before invoking the sync engine:

```go
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:

```yaml
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:

```yaml
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:

```yaml
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:

```bash
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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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.