ArgoCD Applications & Sync
ArgoCD Applications & Sync
An Application is ArgoCD's fundamental unit of work. It binds a Git source (a repo + path + target revision) to a Kubernetes destination (a cluster + namespace) and continuously compares what is in Git against what is running in the cluster. Understanding exactly how that comparison loop works — and how to tune it — is the difference between a GitOps workflow that teams trust and one that generates noise and manual toil.
The Application Manifest
You define an Application as a Kubernetes custom resource (kind Application, API group argoproj.io/v1alpha1) and commit it to Git, or create it via the CLI or UI. The key fields are spec.source (where the desired state lives), spec.destination (where to apply it), and spec.syncPolicy (how and when to reconcile).
Sync Policies: Manual vs Automated
Without syncPolicy.automated, an Application stays in OutOfSync status when drift is detected, but does nothing on its own. An engineer must click "Sync" in the UI or run argocd app sync my-api. This is the right default for production environments where changes need a human gate — automated sync in prod is a team trust and maturity decision, not a technical one.
With automated enabled, ArgoCD immediately syncs whenever the live state diverges from Git. The two sub-fields that matter most:
prune: true— Resources that exist in the cluster but no longer exist in Git are deleted. Without this, deleted manifests leave orphaned Deployments, Services, and ConfigMaps silently running forever — a common source of security and cost surprises. Enable it; pair it withPrunePropagationPolicy=foregroundso dependents are deleted before owners.selfHeal: true— If someone runskubectl applydirectly on the cluster (breaking the GitOps contract), ArgoCD detects the drift within the poll interval and reverts the live state back to Git within seconds. This is what enforces the single-source-of-truth guarantee.
automated + prune on day one in production without first auditing what resources exist in the cluster versus what is tracked in Git. ArgoCD will faithfully delete everything it cannot find in the target path — including resources that belong to other systems or were created manually. Identify and codify orphans first.Sync Waves: Ordering Deployments
Kubernetes applies all resources in a sync operation concurrently by default. That creates problems when ordering matters: a Deployment that depends on a ConfigMap being present, a Job that must complete before an application starts, or a CRD that must exist before its instances. ArgoCD solves this with sync waves.
Assign a wave number to any resource via the annotation argocd.argoproj.io/sync-wave. Resources in wave -1 are applied first, then wave 0 (the default), then wave 1, and so on. ArgoCD waits for all resources in wave N to be healthy before proceeding to wave N+1.
Controlling the Sync from the CLI
The argocd CLI is essential for scripting sync operations in CI pipelines and for incident response. Key commands:
argocd app sync --timeout combined with argocd app wait --health as a post-deploy gate. This blocks the pipeline until the rollout reaches Healthy status — giving you a real signal that the new version is serving traffic before the pipeline marks the deploy green. Pair it with alerting on Degraded transitions in your monitoring stack.Sync Options Worth Knowing
The spec.syncOptions list lets you tune behaviour per Application:
ApplyOutOfSyncOnly=true— Skips applying resources that are already in sync. Dramatically speeds up syncs for large Applications with hundreds of resources. Enable for all applications beyond ~20 resources.ServerSideApply=true— Useskubectl apply --server-sideinstead of client-side apply. Eliminates the "too long annotation" error on large CRDs and ConfigMaps, and correctly handles field ownership when multiple controllers manage the same resource.RespectIgnoreDifferences=true— Tells the sync engine to honour thespec.ignoreDifferencesrules when deciding whether to apply a resource, not just when calculating diff status. Prevents unnecessary re-applies on resources managed by admission webhooks.Replace=true(per-resource annotation) — Forces akubectl replaceinstead ofapplyfor immutable fields likespec.selectoron a Job. Use with care — it deletes and recreates the resource.
spec.ignoreDifferences to exclude specific JSON pointer paths — for example, the caBundle field injected by cert-manager into MutatingWebhookConfiguration objects — so ArgoCD stops reporting phantom drift on resources it does not fully own.The Self-Heal Feedback Loop
With selfHeal: true, the reconciliation loop runs continuously. When a cluster operator runs kubectl scale deployment my-api --replicas=1 during an incident, ArgoCD detects the replica count divergence within the next poll cycle (up to 3 minutes by default, or sooner if webhook delivery is fast) and reverts the deployment back to the replica count declared in Git. This is intentional — the source of truth is Git, not the live cluster. If you need a temporary override, the correct procedure is to commit the override to Git, let ArgoCD apply it, and revert the commit when the incident is resolved. This leaves an audit trail; a bare kubectl command leaves none.