How to Implement Progressive Delivery with Argo CD: RollingSync Strategy Guide

Enable the experimental progressive sync feature in the ApplicationSet controller, then define a RollingSync strategy with ordered steps in your ApplicationSet spec to roll out changes across environments sequentially.

Argo CD’s progressive delivery capability (also referred to as progressive sync) allows you to deploy changes to Kubernetes applications in controlled waves rather than updating all environments simultaneously. This feature is implemented within the ApplicationSet controller and requires explicit activation before use. By configuring a RollingSync strategy, you can orchestrate multi-stage rollouts across development, staging, and production clusters while maintaining fine-grained control over the deployment lifecycle.

Enable Progressive Sync in the Controller

Progressive delivery is an experimental feature in Argo CD. You must enable it before the ApplicationSet controller will process RollingSync strategies.

Using Command-Line Flags

Start the ApplicationSet controller with the --enable-progressive-syncs flag. This option is defined in [cmd/argocd-applicationset-controller/commands/applicationset_controller.go](https://github.com/argoproj/argo-cd/blob/master/cmd/argocd-applicationset-controller/commands/applicationset_controller.go#L311):

argocd-applicationset-controller --enable-progressive-syncs

Using ConfigMap Parameters

Alternatively, enable the feature via the argocd-cmd-params-cm ConfigMap by setting the applicationsetcontroller.enable.progressive.syncs key:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
data:
  applicationsetcontroller.enable.progressive.syncs: "true"

Configure a RollingSync Strategy

Once enabled, define your rollout sequence in an ApplicationSet resource using the strategy field. The API types are defined in [pkg/apis/application/v1alpha1/applicationset_types.go](https://github.com/argoproj/argo-cd/blob/master/pkg/apis/application/v1alpha1/applicationset_types.go#L89-L96).

The following example demonstrates a three-wave rollout across environments:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: progressive-sync-appset
spec:
  generators:
    - list:
        elements:
          - environment: dev
            namespace: dev-ns
          - environment: staging
            namespace: staging-ns
          - environment: prod
            namespace: prod-ns
  template:
    metadata:
      name: '{{name}}-{{environment}}'
      labels:
        environment: '{{environment}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/repo
        targetRevision: HEAD
        path: '{{environment}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{namespace}}'
  strategy:
    type: RollingSync
    rollingSync:
      steps:
        - matchExpressions:
            - key: environment
              operator: In
              values: ["dev"]
          maxUpdate: 100%
        - matchExpressions:
            - key: environment
              operator: In
              values: ["staging"]
        - matchExpressions:
            - key: environment
              operator: In
              values: ["prod"]

Key configuration elements:

  • type: RollingSync – Activates the progressive delivery mode for this ApplicationSet.
  • steps – Defines the order of deployment. Each step contains matchExpressions that select Applications based on their labels.
  • maxUpdate – Optional parameter limiting how many Applications can update simultaneously within a step (e.g., "50%" or an integer).
  • deletionOrder – Optional field set to Reverse to delete Applications in the opposite order of deployment when the ApplicationSet is removed.

How the Progressive Sync Manager Works

The core logic resides in [applicationset/progressivesync/progressive_sync.go](https://github.com/argoproj/argo-cd/blob/master/applicationset/progressivesync/progressive_sync.go). The progressive sync manager orchestrates the rollout by tracking each Application through a defined state machine.

When a generated Application’s desired spec or Git revision changes, the manager transitions its status through the following phases:

  1. Waiting – The Application is queued for the next sync wave.
  2. Pending – The Application is eligible for sync but waiting for the current step to complete.
  3. Progressing – The Application is actively syncing.
  4. Healthy – The Application has synced successfully and the step is complete.

The manager determines which Applications are ready to synchronize using the getAppsToSync function. It builds a dependency list for each step based on the matchExpressions defined in your strategy, ensuring that waves proceed sequentially only after the previous step reaches Healthy status. The status transition logic is implemented around lines 222–390 in the progressive sync manager.

Monitor Rollout Progress

Observe the current state of your progressive delivery by inspecting the ApplicationSet status field. The controller updates ApplicationSet.status.applicationStatus to reflect each Application’s current step and health state.

kubectl get applicationset progressive-sync-appset -o yaml | yq .status.applicationStatus

Expected output shows the progression through steps:

- application: progressive-sync-appset-dev
  status: Healthy
  step: "1"
- application: progressive-sync-appset-staging
  status: Progressing
  step: "2"
- application: progressive-sync-appset-prod
  status: Waiting
  step: "3"

The controller updates these fields automatically as each wave completes. Applications remain in Waiting status until all Applications in the previous step report Healthy.

Configure Reverse Deletion Order (Optional)

When deleting an ApplicationSet configured with progressive sync, you can control the deletion order using the deletionOrder: Reverse setting. This ensures Applications are removed in the opposite sequence of deployment (e.g., production first, then staging, then development).

The PerformReverseDeletion function in [applicationset/progressivesync/progressive_sync.go](https://github.com/argoproj/argo-cd/blob/master/applicationset/progressivesync/progressive_sync.go) handles this logic. This capability is particularly useful for ensuring that cleanup operations respect dependency chains or for maintaining safety during environment teardown.

Summary

  • Progressive delivery in Argo CD requires enabling the experimental --enable-progressive-syncs flag or corresponding ConfigMap parameter.
  • Configure rollouts using the RollingSync strategy in your ApplicationSet spec, defining ordered steps with label matchExpressions.
  • The progressive sync manager in applicationset/progressivesync/progressive_sync.go tracks Application status through Waiting → Pending → Progressing → Healthy states.
  • Use maxUpdate to limit concurrency within a step and deletionOrder: Reverse to control teardown sequence.
  • Monitor rollout health via ApplicationSet.status.applicationStatus to verify each wave completes before the next begins.

Frequently Asked Questions

Is progressive delivery with Argo CD production-ready?

No, progressive delivery is currently an experimental feature in Argo CD. You must explicitly enable it using the --enable-progressive-syncs flag or ConfigMap parameter. Review the official documentation for current stability status and upgrade considerations before deploying to production environments.

How does Argo CD determine which Applications belong to which step?

The controller uses label selectors defined in each step’s matchExpressions field. When generating Applications from the template, ensure they include labels that match your criteria (such as environment: dev). The getAppsToSync function in the progressive sync manager filters generated Applications based on these expressions to build the deployment wave.

What happens if an Application fails to sync during a progressive rollout?

If an Application fails to reach Healthy status, the rollout pauses at that step. The controller will not proceed to subsequent steps until all Applications in the current step report Healthy. You must resolve the underlying issue (such as a failed deployment or invalid manifest) and allow the Application to sync successfully before the progressive delivery continues.

Can I limit the number of concurrent updates within a single step?

Yes. Use the maxUpdate field within a step definition to control concurrency. You can specify an absolute number (e.g., maxUpdate: 2) or a percentage (e.g., maxUpdate: 50%) of Applications that should sync simultaneously. This limits the blast radius during updates and helps manage resource contention in large environments.

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 →