# Argo CD GitOps Workflow Explained: Architecture and Implementation

> Understand the Argo CD GitOps workflow. See how it compares Git desired state with live Kubernetes and automatically reconciles drift through its architecture and implementation.

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

---

**Argo CD implements a declarative GitOps continuous delivery pipeline that continuously compares desired state stored in Git with live Kubernetes cluster state, automatically reconciling drift through a controller loop that executes seven distinct stages from source fetch to status update.**

Argo CD is a Kubernetes-native continuous delivery tool maintained in the `argoproj/argo-cd` repository. It enforces the GitOps methodology by treating Git repositories as the single source of truth for application definitions. Understanding the **Argo CD GitOps workflow** requires examining how the `ApplicationController` orchestrates manifest generation, diff calculation, and synchronized deployment without manual intervention.

## The Seven Stages of the Argo CD GitOps Workflow

The workflow progresses through seven logical stages implemented across the controller and gitops-engine packages. Each stage handles a specific transformation from source code to running cluster resources.

### 1. Source Fetch

The controller reads the Git, OCI, Helm, Kustomize, or Jsonnet repository defined in an `Application` resource. In [`controller/appcontroller.go`](https://github.com/argoproj/argo-cd/blob/main/controller/appcontroller.go) (lines 18-23), the `ApplicationController` initializes a `RepoServer` client to fetch raw manifests from the configured source location.

### 2. Manifest Generation (Hydration)

When the source uses templating tools, the **hydrator** renders "dry" manifests into plain Kubernetes YAML. The implementation in [`controller/hydrator/hydrator.go`](https://github.com/argoproj/argo-cd/blob/main/controller/hydrator/hydrator.go) defines `hydrator.Dependencies` and produces fully rendered manifests required for accurate cluster comparison.

### 3. Diff and Health Analysis

The rendered manifests are compared against live objects in the target cluster. The controller invokes `argodiff.StateDiff` (lines 438-447 in [`controller/appcontroller.go`](https://github.com/argoproj/argo-cd/blob/main/controller/appcontroller.go) utilizing `gitops-engine/v3/pkg/diff`) to calculate declarative differences while masking secret data. Simultaneously, `gitops-engine/v3/pkg/health` determines resource health status, marking any divergence as `OutOfSync`.

### 4. Sync Decision

Based on `Application.Spec.SyncPolicy` and user requests, Argo CD decides whether to **auto-sync**, **manually sync**, or skip reconciliation. The `ApplicationController.requestAppRefresh` method (lines 998-1016) queues refresh requests into the `appRefreshQueue` when drift is detected.

### 5. Apply Changes

Argo CD generates a patch or full manifest and applies it to the target cluster using the Kubernetes client abstraction. The controller utilizes `kube.Kubectl` (lines 22-24) while respecting configured parallelism limits (lines 36-38) to prevent API server overload during bulk operations.

### 6. Status Update

After operations complete, the controller updates the `Application` status with sync results, health conditions, and resource metadata. The `setAppManagedResources` method (lines 998-1020 in [`controller/appcontroller.go`](https://github.com/argoproj/argo-cd/blob/main/controller/appcontroller.go)) persists these updates, while operational metrics are recorded via `metrics.MetricsServer`.

### 7. Events and Metrics

All actions generate audit events via `argo.AuditLogger` and Prometheus metrics through [`controller/metrics/metrics.go`](https://github.com/argoproj/argo-cd/blob/main/controller/metrics/metrics.go). These components are instantiated during `NewApplicationController` initialization (lines 21-31), providing complete observability into the reconciliation loop.

## Continuous Reconciliation Architecture

Argo CD runs a **watch** using the Kubernetes informer pattern on `Application` CRDs hosted in the cluster. When changes occur in Git (triggered by webhooks or periodic polling) or in live cluster resources, the controller enqueues a refresh request to the `appRefreshQueue`. Worker threads process these requests asynchronously, guaranteeing eventual consistency between the version-controlled desired state and the actual cluster state.

The **source of truth** remains exclusively the Git repository. All changes applied to the live cluster trace back to specific commits, enabling complete audit trails and simple rollbacks by reverting Git history.

## Key Implementation Files

Understanding the Argo CD GitOps workflow requires familiarity with these critical source locations:

- **[`controller/appcontroller.go`](https://github.com/argoproj/argo-cd/blob/main/controller/appcontroller.go)** – Main controller loop, queue handling, and sync orchestration
- **[`controller/hydrator/hydrator.go`](https://github.com/argoproj/argo-cd/blob/main/controller/hydrator/hydrator.go)** – Renders Helm/Kustomize/Jsonnet templates into executable YAML
- **`gitops-engine/v3/pkg/diff`** – Calculates declarative differences between desired and live state
- **`gitops-engine/v3/pkg/health`** – Determines real-time health status of Kubernetes resources
- **[`controller/metrics/metrics.go`](https://github.com/argoproj/argo-cd/blob/main/controller/metrics/metrics.go)** – Exposes Prometheus metrics and tracks kubectl usage patterns
- **[`controller/sharding/sharding.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sharding/sharding.go)** – Distributes workload across multiple controller replicas for horizontal scaling
- **[`util/db/db.go`](https://github.com/argoproj/argo-cd/blob/main/util/db/db.go)** – Persists application state in a ConfigMap-backed database

## Practical Example: From Git Commit to Live Cluster

Below is a minimal `Application` resource demonstrating automated synchronization:

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/guestbook
    targetRevision: HEAD
    path: kustomize
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

```

The execution flow follows these steps:

1. **Git Fetch** – The controller contacts the repo server via `repoClientset` and pulls the `kustomize` directory at `HEAD`.
2. **Hydration** – Kustomize renders the files into canonical YAML manifests through the hydrator.
3. **Diff Calculation** – `argodiff.StateDiff` compares rendered manifests against objects currently in the `default` namespace.
4. **Automatic Sync** – Because `automated.selfHeal` is enabled, detected drift triggers `kubectl apply` through the `kube.Kubectl` wrapper.
5. **Status Recording** – The `Application` status updates to `Synced` and records the specific commit SHA that produced the live state.

## Summary

The Argo CD GitOps workflow consists of tightly integrated components that automate Kubernetes deployments:

- **Application CR** declares what should run and where, storing references to the desired state in Git.
- **ApplicationController** manages the core reconciliation loop, fetching source, rendering manifests, and applying changes.
- **Hydrator** converts template-based configurations into concrete Kubernetes YAML before comparison.
- **Diff and Health Engine** calculates drift and determines whether resources are healthy, degraded, or missing.
- **Sharding** enables horizontal scaling across multiple controller replicas for high-volume environments.
- **Metrics and Auditing** provide operational visibility and immutable audit trails for compliance.

This architecture ensures the live cluster always reflects the version-controlled desired state without requiring manual kubectl operations.

## Frequently Asked Questions

### How does Argo CD detect changes in the Git repository?

Argo CD detects changes through webhook notifications from Git providers that trigger immediate reconciliation, and through periodic polling intervals that scan repositories for new commits. When either mechanism identifies drift, the controller enqueues a refresh request to the `appRefreshQueue` for processing by worker threads according to the logic in [`controller/appcontroller.go`](https://github.com/argoproj/argo-cd/blob/main/controller/appcontroller.go).

### What is the difference between auto-sync and manual sync in Argo CD?

**Auto-sync** automatically applies changes when drift is detected between Git and the cluster, configured via `syncPolicy.automated` in the Application spec with options like `prune` and `selfHeal`. **Manual sync** requires explicit user approval through the UI or CLI before the controller executes any changes. Auto-sync provides hands-free continuous delivery, while manual sync offers greater control for production environments requiring change review.

### How does Argo CD handle secret management during the diff process?

According to the implementation in `gitops-engine/v3/pkg/diff`, Argo CD masks sensitive data during diff calculations to prevent secret values from appearing in logs and UI displays. The diff engine compares live state against desired state while redacting secret contents, ensuring security compliance while still identifying configuration drift in non-sensitive fields.

### Can Argo CD scale to manage thousands of applications?

Yes, Argo CD supports horizontal scalability through **sharding** implemented in [`controller/sharding/sharding.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sharding/sharding.go). Multiple controller replicas run simultaneously, with each replica processing a distinct shard of applications based on cluster hostname or application UID. This distribution prevents any single controller from becoming a bottleneck and enables high-availability deployments across multiple nodes.