You've created your first ArgoCD Application in Chapter 8. Now comes a critical decision: When and how should ArgoCD sync changes to your cluster?
By default, ArgoCD doesn't automatically sync. You must click "Sync" in the UI or run argocd app sync. This gives you control but requires constant attention. Real GitOps teams use automated sync policies to eliminate manual intervention while still maintaining safety.
In this chapter, you'll learn how to configure sync strategies that match your deployment goals:
By the end of this chapter, you'll understand the tradeoffs and be able to configure sync policies that work for your team.
Manual sync is the default. You must explicitly trigger deployments. This makes sense when:
When you create an Application in Chapter 8, if you don't specify syncPolicy, it defaults to manual:
Output:
Output:
In production:
Auto-sync means: "Whenever Git changes, automatically apply those changes to the cluster." This is true GitOps.
Add syncPolicy.automated to your Application:
Output:
All without manual intervention.
You can fine-tune auto-sync behavior:
Each setting addresses a specific concern:
We'll explore prune and selfHeal below. For now, know that automated: {} means:
When you remove a resource from your Git repository, what happens to the instance already running in the cluster?
Without auto-prune: The resource stays in the cluster even though it's not in Git anymore. You have orphaned resources.
With auto-prune: ArgoCD automatically deletes the resource.
You have a service in Git:
Your Application has it synced:
Output:
Now you delete k8s/service.yaml from your Git repo and push.
If auto-prune is DISABLED:
Output:
The service still exists. ArgoCD only cares about applying what's in Git, not removing what's not.
If auto-prune is ENABLED:
Push the same deletion to Git. ArgoCD applies changes:
Output:
Enable prune when:
Disable prune when:
Start with prune: false and increase your git discipline:
Once you're confident:
Then enable:
Sometimes you or a colleague manually changes something in the cluster:
Now the cluster state (10 replicas) doesn't match Git state (3 replicas). You have drift.
Without self-heal: The cluster keeps the manual change. Your Git is out of sync.
With self-heal: ArgoCD detects the drift and reverts the cluster back to what Git says.
Your Application currently has:
Someone manually scales it:
Check the cluster:
Output:
The cluster now has 10 replicas (manual change).
If self-heal is DISABLED:
The cluster stays at 10 replicas. ArgoCD doesn't care about drift—it only syncs when Git changes. Your Git and cluster are out of sync.
If self-heal is ENABLED:
ArgoCD checks every 3 seconds (default). When it detects the drift:
Output:
The cluster is healed back to Git state.
Enable when:
Disable when:
Self-heal automatically reverts changes. This is powerful but risky:
Safety strategy: Keep self-heal off in staging until you're confident. Test it thoroughly. Only enable in production once you trust it.
Sometimes you need to change a resource that Kubernetes won't let you modify with kubectl apply. This is where the syncStrategy comes in.
Kubernetes immutability rules vary by resource type. For example, you can't change a Service's selector with kubectl apply:
If you try to apply a new Service with a different selector:
Output:
Tell ArgoCD to delete and recreate the resource instead of applying changes:
Now when you change the selector, ArgoCD:
For a Service, Replace means a few seconds of downtime (clients can't reach the service). For a Deployment, Replace means pods restart.
Use Replace only when necessary (immutable field changes). Use Apply (default) for most updates.
Sometimes you need to say: "Don't deploy between 9 AM and 10 AM because we're doing live demos."
Sync windows let you restrict when deployments can happen.
Add syncPolicy.syncWindows:
The Application has two windows defined:
If a deployment is triggered outside these windows:
This means: "I only want deployments on Sunday mornings from 2-6 AM. Any other time, block."
This means: "Don't deploy Mon-Fri 9-5 (business hours). Any other time, deploy freely."
Sync windows use cron syntax: minute hour day month dayOfWeek
Use crontab.guru to build cron expressions.
What if a critical bug needs deploying during a deny window?
Option 1: Manual sync overrides the window
Option 2: Edit the Application to remove the sync window temporarily
Here's a quick reference for common scenarios:
No automation. You control everything. Good for understanding the workflow.
Full automation in staging. Let it fail fast so you catch issues before production.
Auto-sync with self-heal, but:
Manual sync for every deployment. Gives you control but requires active management.
Once you understand the policies, you can update an existing Application:
Add or modify the syncPolicy section. Save and exit your editor.
Output:
Verify the change:
Output:
Now that you understand sync strategies, ask Claude to help you navigate tradeoffs:
Setup: Open your Application YAML from Chapter 8 (or create a sample one)
Prompt 1: "I want to enable auto-sync for my staging environment, but I'm worried about auto-prune deleting important resources. Should I enable auto-prune? What's a safer approach?"
When Claude responds, evaluate:
Prompt 2: "Our team keeps making emergency manual changes to production, but self-heal keeps reverting them. How should we structure our sync policies to allow emergency changes while still having Git as truth?"
Evaluate the response:
Prompt 3: "Write a sync window that only allows deployments on weekdays between 2-4 AM UTC, except during the first Monday of each month when we do major releases (allow anytime that day)."
Review the YAML:
Iterate: Take Claude's answers and apply them to your actual Application. Verify the sync behavior matches your expectations by:
You built a gitops-deployment skill in Chapter 0. Test and improve it based on what you learned.
Ask yourself:
If you found gaps: