ArgoCD and Flux are the two CNCF graduated GitOps tools for Kubernetes. Both sync desired state from Git to clusters. The main difference: ArgoCD provides a rich UI and application-centric model. Flux provides a toolkit of controllers with no built-in UI.
Architecture
ArgoCD
ArgoCD is an application-centric GitOps controller:
- Application CRD β each deployment is an Application resource pointing to a Git repo + path
- Web UI β full dashboard showing sync status, diffs, resource trees
- API server β REST/gRPC API for CLI and UI
- Application controller β watches Applications and syncs to clusters
- Repo server β clones Git repos, renders Helm/Kustomize templates
Flux
Flux is a toolkit of independent controllers:
- Source controller β fetches from Git, Helm, OCI, S3
- Kustomize controller β applies Kustomize overlays
- Helm controller β manages Helm releases via HelmRelease CRDs
- Notification controller β sends alerts to Slack, Teams, etc.
- Image automation β updates image tags in Git automatically
Each controller operates independently β you can use only the ones you need.
Feature comparison
| Feature | ArgoCD | Flux |
|---|---|---|
| UI | Built-in web dashboard | No UI (use Weave GitOps, Capacitor) |
| CLI | argocd CLI | flux CLI |
| Application model | Application CRD | GitRepository + Kustomization CRDs |
| Helm support | Via Application (render) | HelmRelease CRD (native) |
| Kustomize | Via Application | Kustomization CRD (native) |
| OCI artifacts | Yes | Yes (first-class) |
| Multi-cluster | ApplicationSets, hub-spoke | Kustomization with remote clusters |
| RBAC | Built-in (projects, roles) | Kubernetes RBAC |
| SSO | Built-in (OIDC, LDAP, SAML) | No (cluster-level auth) |
| Sync waves/hooks | Yes (ordering, hooks) | Depends-on ordering |
| Diff preview | UI + CLI (argocd diff) | CLI (flux diff) |
| Notifications | Notification CRD | Notification controller |
| Image automation | Via Argo Image Updater | Built-in Image automation |
| Multi-tenancy | AppProjects | Namespace-scoped controllers |
| Pruning | Configurable per app | Configurable per kustomization |
| Health checks | Built-in (Lua scripts) | Via Kustomize health checks |
| CNCF | Graduated | Graduated |
UI and developer experience
ArgoCD: visual GitOps
ArgoCDβs UI is its biggest differentiator:
- Application dashboard: See all applications, their sync status, and health at a glance
- Resource tree: Visual representation of Deployments β ReplicaSets β Pods
- Live diff: Compare desired (Git) vs actual (cluster) state
- Sync with one click: Manual sync from the UI
- RBAC per project: Different teams see different applications
This matters in organizations where developers (not just platform engineers) need visibility into deployment state.
Flux: CLI-first
# Check what Flux is doing
flux get all
# See sync status
flux get kustomizations
# NAME READY MESSAGE
# production True Applied revision: main@sha1:abc123
# staging True Applied revision: main@sha1:abc123
# Reconcile immediately
flux reconcile kustomization production
# Check events
flux eventsFlux is operator-friendly but provides no built-in visibility for developers. Third-party UIs exist (Weave GitOps, Capacitor) but are less mature than ArgoCDβs UI.
Helm handling
ArgoCD
ArgoCD renders Helm charts server-side via its repo server:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx
spec:
source:
repoURL: https://charts.bitnami.com/bitnami
chart: nginx
targetRevision: 15.x
helm:
values: |
replicaCount: 3
service:
type: ClusterIP
destination:
server: https://kubernetes.default.svc
namespace: productionArgoCD renders the chart into manifests and tracks the rendered output. The Helm release is not visible to helm list because ArgoCD manages it directly.
Flux
Flux uses a native HelmRelease CRD that actually creates Helm releases:
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: nginx
namespace: production
spec:
interval: 5m
chart:
spec:
chart: nginx
version: "15.x"
sourceRef:
kind: HelmRepository
name: bitnami
values:
replicaCount: 3
service:
type: ClusterIPFlux Helm releases are visible to helm list and follow standard Helm lifecycle (install β upgrade β rollback).
Multi-cluster
ArgoCD: hub-spoke with ApplicationSets
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: nginx-everywhere
spec:
generators:
- clusters:
selector:
matchLabels:
environment: production
template:
metadata:
name: "nginx-{{name}}"
spec:
source:
repoURL: https://github.com/myorg/apps
path: nginx
destination:
server: "{{server}}"
namespace: productionApplicationSets generate Applications dynamically for each matching cluster. The ArgoCD hub manages all clusters from a single control plane.
Flux: decentralized
Each cluster runs its own Flux controllers, syncing from the same Git repo with cluster-specific overlays. No central hub.
repo/
βββ base/
β βββ nginx/
βββ clusters/
β βββ production-eu/
β β βββ kustomization.yaml # patches for EU
β βββ production-us/
β βββ kustomization.yaml # patches for USPerformance at scale
| Metric | ArgoCD | Flux |
|---|---|---|
| Applications/cluster | 1,000+ (with sharding) | 1,000+ |
| Clusters managed | 100+ (from hub) | Per-cluster (decentralized) |
| Memory (1000 apps) | ~4 GB (controller + repo server) | ~1 GB (controllers) |
| Reconciliation speed | Configurable (default 3 min) | Configurable (default 1 min) |
| Git polling | Per-app interval | Per-source interval |
Flux is lighter because it has no UI, API server, or repo server. ArgoCD uses more resources but provides more features per resource consumed.
Decision guide
Choose ArgoCD when:
- Developer visibility matters β teams need a UI to see deployment status
- You want centralized multi-cluster management from a single hub
- RBAC and SSO are requirements (built-in OIDC, LDAP)
- You need sync waves and hooks for complex deployment ordering
- Your organization values a polished developer experience
Choose Flux when:
- You prefer a lightweight, CLI-first approach
- Each cluster should be self-managing (no central hub)
- You want native Helm release management (
helm listvisibility) - OCI artifacts are your primary distribution mechanism
- You are building a platform engineering toolkit and want composable controllers
- Resource efficiency matters β Flux uses less memory per cluster