← Back to blog
GitOps4 min read

ArgoCD vs Flux: choosing a GitOps engine (from someone who runs both)

gitopsargocdfluxcdkubernetes

I get the "ArgoCD or Flux?" question often, and my answer pleases nobody: it depends. Not because I'm dodging it, but because I run both in production — ArgoCD on on-prem RKE2 clusters with app-of-apps, Flux on Azure/AKS. Both do the job well. They differ in how they do it, and that's what decides.

The shared model

Whatever you pick, you get the same foundation: Git as the single source of truth, a pull-based reconcile loop running inside the cluster, and continuous comparison of desired state (Git) against actual state (the API server). No kubectl apply from CI, no cluster credentials shipped out. The controller pulls manifests itself. That's the entire core of GitOps, and neither tool differs here.

The difference is the packaging philosophy. ArgoCD is a product. Flux is a set of controllers.

ArgoCD: an application with an opinion

ArgoCD revolves around the Application CRD — one Application = one source (repo + path/Helm chart) mapped to a target cluster and namespace. ApplicationSet generates those Applications in bulk (Git, list, cluster, matrix generators), which is indispensable when you run the same stack across dozens of clusters.

Bootstrapping is handled by app-of-apps — a single root Application pointing at a directory of more Applications. That's exactly what I run on-prem. Ordering is done with sync waves (the argocd.argoproj.io/sync-wave annotation; lower numbers go first — typically CRDs at -5, operators -3, infra -1, apps 1+) and resource hooks with PreSync / Sync / PostSync phases for migrations, smoke tests, and the like.

And then there's the web UI. This is why teams pick ArgoCD more often than they admit. Seeing a diff, the resource tree, why an app is OutOfSync, clicking rollback — for dev teams that don't live in kubectl, that's a huge difference.

Flux: the GitOps Toolkit

Flux isn't one app, it's the GitOps Toolkit — a set of specialized controllers:

  • source-controller — pulls artifacts from Git and Helm repositories
  • kustomize-controller — applies manifests (the Kustomization CRD)
  • helm-controller — declarative Helm (the HelmRelease CRD)
  • notification-controller — events, alerts, inbound webhooks
  • image-reflector-controller + image-automation-controller — image automation (GA since Flux 2.7)

No built-in UI. A minus for some; for me on Azure, a plus — observability goes through Prometheus metrics and Grafana, where everything flows anyway, and I read state with flux get. Flux is more honestly "GitOps-native" and composable: you deploy only the controllers you actually need.

Image automation — the biggest real difference

This is where the tools diverge most. Flux treats image automation as a first-class feature: the reflector scans registries for new tags, the automation controller commits the updated image reference back to Git. Declarative, auditable, via dedicated CRDs.

ArgoCD does not natively detect new tags. You need the separate Argo CD Image Updater — a companion project that's still less mature and driven by annotations. Fine for a handful of apps; at scale the annotations get hard to manage. When auto-bumping images is a hard requirement, Flux does it more cleanly.

Secrets

Flux has the edge in one specific case: the kustomize-controller decrypts SOPS natively at reconcile time, with no extra controller. Encrypted secrets committed straight into Git work out of the box.

ArgoCD doesn't handle secrets itself — you lean on the ecosystem: Sealed Secrets, External Secrets Operator, or SOPS via a plugin. That's not a weakness, just a different stance. I use ESO in both worlds anyway, because Vault is our source of truth regardless.

Drift, self-heal, ServerSideApply

Both detect drift and can self-heal (revert manual changes back to the Git state). Both support ServerSideApply — with ArgoCD I enable it almost always for CRDs, to dodge the annotation-size limit from client-side apply. One caveat: there was a regression where SSA broke sync-wave ordering on failure — if you run SSA with waves, check your version.

Multi-tenancy

ArgoCD: AppProjects constrain what an app may deploy and where. Flux: namespace-scoped service accounts and Kustomization impersonation. Both are equally easy to get wrong — if you don't design the boundaries before onboarding teams, you end up with an over-privileged controller that can deploy anywhere.

When I reach for which

  • Team wants a UI, click-to-rollback, app-of-apps and ApplicationSets across many clusters → ArgoCD. This is my on-prem default.
  • I want a purely declarative, composable toolkit, native image automation, and SOPS with no extra pieces → Flux. This runs on Azure.

No winner. They're two answers to the same question — and the right one depends on who's going to sit in front of that repo every day.