Argo CD Waves and Phases let you control the order in which your applications are synchronized, not just which ones are synchronized.
Let’s see it in action. Imagine you have a few applications: a database app, a backend app, and a frontend app. You absolutely need the database up and running before the backend can start, and the backend needs to be ready before the frontend can serve traffic.
Here’s how you’d define that dependency using Waves and Phases within an ApplicationSet or directly in an Application’s syncPolicy:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-set
spec:
generators:
- list:
- { name: database, url: https://github.com/my-repo/database.git }
- { name: backend, url: https://github.com/my-repo/backend.git }
- { name: frontend, url: https://github.com/my-repo/frontend.git }
template:
applicationSetTemplate:
template:
metadata:
name: "{{name}}"
spec:
project: default
source:
repoURL: "{{url}}"
targetRevision: HEAD
path: overlays/production
destination:
server: "https://kubernetes.default.svc"
namespace: production
syncPolicy:
syncOptions:
- CreateNamespace=true
waves: # This is where the magic happens!
- wave: 0 # First wave, runs all apps within it concurrently
applications:
- name: database
- wave: 1 # Second wave, runs after wave 0 completes
applications:
- name: backend
- wave: 2 # Third wave, runs after wave 1 completes
applications:
- name: frontend
In this ApplicationSet, we’ve defined three waves. Argo CD will first synchronize the database application. Only after the database application has successfully synchronized will Argo CD proceed to synchronize the backend application in wave 1. Finally, once the backend is up, it will synchronize the frontend application in wave 2.
This gives you fine-grained control. You can also group multiple applications within a single wave if they can be deployed in parallel. For example, if your backend and a cache service could be deployed concurrently, you could put them both in wave 1:
waves:
- wave: 0
applications:
- name: database
- wave: 1
applications:
- name: backend
- name: cache
- wave: 2
applications:
- name: frontend
This is powerful because it allows you to manage complex deployment dependencies and ensure that your applications are brought online in a safe, ordered sequence, preventing runtime errors caused by missing dependencies. It’s not just about what gets deployed, but when and in what order relative to other deployments.
The default behavior for applications within the same wave is parallel synchronization. If you need even finer control within a wave, you can introduce phases. Phases are a more granular way to define ordering within a specific wave. For instance, if within wave 1, you needed the cache to start before the backend (even though they are both in wave 1 and would otherwise start concurrently), you could use phases:
waves:
- wave: 0
applications:
- name: database
- wave: 1
phases: # Introducing phases within wave 1
- phase: 0 # First phase in wave 1
applications:
- name: cache
- phase: 1 # Second phase in wave 1
applications:
- name: backend
- wave: 2
applications:
- name: frontend
Here, within wave 1, the cache will be synchronized first (phase 0). Only after the cache is synced will the backend be synchronized (phase 1). This allows for very intricate deployment sequences.
A common misconception is that Waves and Phases are just a way to slow down deployments. In reality, they are crucial for managing stateful applications or services with strict interdependencies. Without them, attempting to deploy a web application that relies on a database might fail if the database isn’t ready, or if the database deployment itself has dependencies that need to be met first. Waves and Phases provide the explicit ordering necessary to avoid these cascading failures.
When you see the Application resources in Argo CD, you’ll notice the health.status and sync.status fields. Waves and Phases directly influence when these statuses transition to Healthy and Synced for each application in the defined sequence.
The next step after mastering ordered synchronization is understanding how to implement automated rollbacks based on synchronization failures across waves.