Skip to main content
After running both in production across a dozen clusters, here's where Flux and Argo CD actually differ and which one we'd reach for now.

Flux vs Argo CD: Picking a GitOps Engine in 2026

KU
Kiril Urbonas
3 months ago • 4 min read•12 views

After running both in production across a dozen clusters, here's where Flux and Argo CD actually differ and which one we'd reach for now.

Key takeaways

After running both in production across a dozen clusters, here's where Flux and Argo CD actually differ and which one we'd reach for now.

Flux vs Argo CD: Picking a GitOps Engine in 2026#

We inherited a Flux v1 setup that nobody understood and an Argo CD instance that three teams were fighting over. Consolidating them forced a real decision instead of a whiteboard debate, and the answer wasn't what the loudest engineer wanted. Here's what actually mattered once both were running the same workloads.

How each one thinks about sync#

Argo CD models everything as an Application. You point it at a repo path, and it reconciles the live cluster state against the manifests. The mental model is object-centric: you have a thing called an app, it has a health status, you look at it in a UI.

Flux is a set of controllers that each do one job. source-controller pulls the Git repo, kustomize-controller applies it, helm-controller handles charts, notification-controller sends alerts. There's no single "app" object unless you build one. It's more Unix-y, more composable, and there's less magic to reason about when something breaks.

A minimal Flux setup looks like this:

yaml.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: platform
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/acme/platform-config
  ref:
    branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 5m
  path: ./clusters/prod
  prune: true
  sourceRef:
    kind: GitRepository
    name: platform

The equivalent Argo Application:

yaml.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: apps
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/acme/platform-config
    targetRevision: main
    path: clusters/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Note selfHeal: true in Argo. That's the setting that reverts manual kubectl edit changes back to Git. Flux does this by default through its reconcile loop; you turn it off with spec.suspend. Different defaults, same capability.

The UI question is not small#

Argo CD's UI is the reason most teams pick it, and I'll be honest, it earns that. The topology view showing pods, replicasets, and ingress with live health status is genuinely useful during an incident. When a rollout is stuck, you see the failing resource in two clicks. Non-platform engineers can self-serve a sync without touching a terminal.

Flux has no first-party UI. You get flux get kustomizations on the CLI and whatever you build into Grafana from its metrics. The Weave GitOps dashboard existed but its future is murky after the Weaveworks shutdown, so I wouldn't bet a platform on it in 2026. If your developers expect a dashboard, that's a real cost with Flux.

Multi-tenancy and blast radius#

This is where Flux won for us. Each Kustomization and GitRepository is a namespaced object with its own service account, so you can hand team A a namespace and let them run their own reconciliation without any chance of touching team B's resources. RBAC does the enforcement, and it's Kubernetes-native RBAC, nothing bespoke.

Argo does multi-tenancy through AppProject objects and its own RBAC layer on top of Kubernetes RBAC. It works, but it's a second permission system to reason about, and we caught two misconfigurations where an app could sync to a namespace it shouldn't. Not Argo's fault exactly, but the extra layer is extra surface to get wrong.

Where each one bites you#

Argo CD's application controller is a single point of scale. Past a few thousand applications it starts to sweat, and you shard the controller across replicas, which is fiddly. Flux scales more naturally because the controllers are independent, but debugging a stuck reconcile means reading controller logs and correlating events, which is slower than glancing at a UI.

Both handle Helm well now. Both do image automation, though Flux's image-reflector-controller for auto-bumping tags is more mature than Argo Image Updater, which still feels bolted on.

The call we'd make#

For a platform team running many clusters with strong tenant isolation and engineers who live in the CLI, Flux. It's smaller, composable, and the multi-tenancy story is cleaner. For an org where application teams need to see and drive their own deploys, and where the dashboard reduces support tickets, Argo CD, and it's not close. We ended up standardizing on Argo for the product clusters because the developer self-service saved our platform team hours a week, and kept Flux only on the infrastructure clusters where no human needs a UI.

Explore topics:KubernetesCI/CDDevOps
React

Get the DevOps Troubleshooting Cheat Sheet

Subscribe and get our free one-page reference for the errors that eat an afternoon — CrashLoopBackOff, OOMKilled, Terraform state locks, and more — plus new guides as we publish them.

Share this post
KU

Kiril Urbonas

AI Engineer

560 articles
View all articles by Kiril Urbonas

You might have missed

Evergreen posts worth revisiting.