Argo CD and Flux: revisit your GitOps controller before you scale or migrate
A platform team in Pune looks after 14 Kubernetes clusters. Most of them are managed by one central Argo CD instance that the team set up in 2021. Last year the company acquired a smaller firm, and its six clusters each run Flux, bootstrapped from a Git repository per cluster. Now leadership wants one way of working before the cluster count doubles next year. The developers say they cannot live without the Argo CD screen. The acquired team says Flux is simpler to run and that it survived the Weaveworks shutdown. The security reviewer asks a question nobody has answered yet: why does the deployment tool have rights over everything in every cluster?
All three points are valid, and they pull in different directions. This post compares Argo CD and Flux as they stand today, from history and governance to sync, Helm, tenancy, footprint and upgrades. Facts come from the projects’ repositories, release pages, official docs, CNCF pages and official blogs, checked on 7 October 2026. The drill results are from my own offline run. If you are also replacing your ingress controller, the earlier post on Ingress NGINX retirement covers that side; the GitOps controller is usually what rolls such a change out.
The short version
- Both are CNCF graduated projects under Apache 2.0, and both shipped releases in the last week: Argo CD 3.5.4 (7 October 2026 IST) and Flux 2.9.6 (1 October 2026).
- Argo CD is an application delivery service with its own API, UI, SSO and RBAC. Flux is a set of Kubernetes controllers that rely on Kubernetes RBAC and have no UI in the core project.
- Argo CD renders Helm charts with
helm templateand manages the objects itself. Flux performs real Helm releases through the Helm SDK, sohelm listand Helm history keep working. - Argo CD usually runs as a hub that pushes to many clusters. Flux usually runs inside each cluster and pulls. Both can do the other model too.
- After Weaveworks closed in February 2024, Flux kept its release cadence. Today its nine core maintainers come from ControlPlane, SUSE, two other companies and independents.
- In my drill, the default Flux install had 4 controllers with resource requests and limits set. Argo CD’s
install.yamlhad 7 workloads with no requests or limits at all, and its application controller had a wildcard ClusterRole.
Where things stand on 7 October 2026
Argo CD
Flux
Latest release
3.5.4, 7 October 2026 IST; 3.4.10 and 3.3.15 patches the same night
2.9.6, 1 October 2026
Next
3.6.0-rc2 out; 3.6 GA planned for 3 November 2026
Next minor expected after the next Kubernetes minor
Supported lines
Three most recent minors (3.5, 3.4, 3.3)
Last three minors (2.9, 2.8, 2.7)
Licence
Apache 2.0
Apache 2.0
CNCF status
Graduated, 6 December 2022 (as part of Argo)
Graduated, 30 November 2022
Main backers
Intuit, Akuity, Red Hat, Octopus Deploy and others
ControlPlane, plus maintainers at SUSE and other firms
Built-in UI
Yes
No; separate projects provide one
Optional add-ons
Image Updater 1.3.0, argocd-agent 0.10.0 (both in argoproj-labs)
Image automation controllers, Flux Operator 0.61.0 (ControlPlane)
The timeline, from the repositories, release pages and CNCF pages:
Date
Event
7 July 2016
First Flux commit, by Peter Bourgon at Weaveworks
22 January 2018
Applatix, the company behind Argo Workflows, joins Intuit
13 March 2018
First tagged Argo CD release, v0.1.0
30 August 2018
Argo CD publicly introduced by Intuit and the Argo community
15 July 2019
Flux accepted into the CNCF
26 March 2020
Argo accepted into the CNCF at incubating level
7 April 2021
Argo CD 2.0.0
November and December 2022
Flux (30 November) and Argo (6 December) graduate
5 July 2023
Flux 2.0.0 GA
February 2024
Weaveworks ceases commercial operations; ControlPlane hires Flux core maintainers (15 February); Octopus Deploy acquires Codefresh (27 February)
6 May 2025
Argo CD 3.0.0, the first major version since 2021
24 February 2026
Flux 2.8.0 ships with Helm v4
30 June 2026
Flux 2.9.0: CLI plugins, drift ignore rules
4 August 2026
Argo CD 3.5.0: Helm 4, impersonation beta, ApplicationSet UI
Two designs for the same idea
Both tools read desired state from Git or an OCI registry, compare it with the cluster and apply the difference. They package that loop very differently.
Argo CD is a service. The API server serves the UI, CLI and webhooks, and handles SSO and RBAC. The repo server clones repositories and renders manifests from plain YAML, Kustomize, Helm or plugins. The application controller compares live state with the rendered target and runs sync operations and hooks (PreSync, Sync, PostSync). The ApplicationSet controller generates Applications from templates. A notifications controller, Redis as a cache and Dex for SSO complete the picture. The unit of work is the Application, grouped into AppProjects.
Flux is a toolkit of controllers, each with its own CRDs. source-controller fetches Git, OCI, Helm and S3-compatible sources and turns them into versioned artifacts. kustomize-controller builds and applies them. helm-controller runs Helm releases. notification-controller sends events out and receives webhooks in. Optional controllers handle image scanning, image updates and source composition (source-watcher). There is no Flux API server; the Kubernetes API is the API.
Argo CD 3.5.4
Flux 2.9.6
Main objects
Application, ApplicationSet, AppProject
GitRepository, OCIRepository, HelmRepository, Bucket, Kustomization, HelmRelease, Alert, Provider, Receiver
CRDs in default install
3
11; 15 with optional controllers
Where rendering happens
repo server
kustomize-controller and helm-controller
Access control
Argo CD RBAC on top of Kubernetes
Kubernetes RBAC only
Interfaces
Web UI, argocd CLI, gRPC and REST API
flux CLI, kubectl, third-party UIs
Headless option
Argo CD Core (core-install.yaml)
Always headless
How sync and reconcile work
In Argo CD, the controller refreshes each application on a timer. The argocd-cm reference says the reconciliation timeout is “two minutes by default with additional jitter”, and the jitter defaults to one minute; the HA guide still describes it as polling Git every three minutes. Git webhooks make it near immediate. A refresh only marks an application OutOfSync; the sync is manual unless automated sync is enabled. Even with automated sync, pruning of deleted resources and self-healing of manual cluster edits are off by default.
In Flux, every object has its own interval. source-controller publishes a new artifact when the revision changes, and kustomize-controller applies it with server-side apply. The prune field on a Kustomization is required, so you must decide garbage collection explicitly for each one. Ordering is done with dependsOn between Kustomizations or HelmReleases, and health checks with wait or explicit checks.
Default behaviour
Argo CD
Flux
Check for new commits
About 2 to 3 minutes, plus webhooks
Per object interval, plus Receivers
Apply automatically
Off until automated sync is set
Yes, at every interval
Delete removed objects
Off until prune: true
Required choice on every Kustomization
Undo manual edits
Off until selfHeal: true
Yes, at every interval
Apply method
Client-side apply; ServerSideApply=true per app or resource
Server-side apply
In short, Argo CD lets a team look before syncing, while Flux treats the commit as the gate.
Drift detection
Argo CD shows drift as a diff in the UI and CLI. Its docs list reasons an application stays OutOfSync right after a sync: mutating webhooks, controllers changing fields, charts using random functions and HPAs reordering metrics. ignoreDifferences handles those, and self-heal decides whether drift is corrected or only reported.
Flux runs a server-side apply dry run at each interval and corrects what differs. Until 2.9, this meant Flux fought any other controller that owned a field, such as an HPA setting replicas. Flux 2.9 added spec.ignore rules on Kustomizations for exactly this. For Helm, drift detection is a separate, optional setting on each HelmRelease: warn reports drift as events, and enabled also corrects it.
Helm and Kustomize
This is where many migrations hurt.
Argo CD
Flux
How Helm runs
helm template, then Argo CD applies and owns the objects
Helm SDK install, upgrade, test, rollback
helm list and history
Empty; no Helm release exists
Normal Helm releases in Helm storage
Hooks
Mapped onto Argo CD hooks; the docs call it “annotation compatibility”
Native Helm hooks; 2.9 changed the default post-render strategy to include hooks
Failure handling
Sync status and retry options
Remediation: retries, rollback or uninstall
Helm 4
Since 3.5
Since 2.8
Kustomize
kustomize build plus overrides in the Application
Built in, plus postBuild variable substitution
Kustomize exec plugins
Possible through build options or config management plugins
Not allowed, for security reasons
helm rollback runbooks work with Flux, not with Argo CD-managed charts, and charts relying on hook ordering need testing under Argo CD. Going the other way, Flux 2.9’s post-render default change is listed as breaking, so set the strategy explicitly before upgrading.
Multi-cluster: hub or per-cluster
Argo CD’s common model is a hub. One instance holds cluster credentials as secrets and pushes to each cluster. ApplicationSets with list, cluster, Git and matrix generators stamp out one Application per cluster or folder. At scale, the application controller is sharded across replicas by cluster (legacy, round-robin or the experimental consistent-hashing method). The hub needs network reach and strong credentials for every cluster. argocd-agent, still at 0.x in argoproj-labs, turns this into a pull model where agents in each cluster connect back to the hub.
Flux’s common model is one installation per cluster, each reconciling its own path in Git. Nothing outside needs credentials to it. Flux can also act as a hub, pointing a Kustomization or HelmRelease at a remote cluster through spec.kubeConfig. For very large numbers of objects, Flux shards controllers by a sharding.fluxcd.io/key label.
If your real problem is placing add-ons across hundreds of clusters by labels, Rancher Fleet (0.16.2) and Sveltos (1.16.0) target that layer. Sveltos says it extends Argo CD or Flux rather than replacing them.
Multi-tenancy, RBAC and SSO
Argo CD has its own security model. AppProjects restrict which repositories, destinations and kinds a team can use, and Casbin-style CSV policies define who can sync, delete, read logs or exec. SSO works through the bundled Dex or an existing OIDC provider. Version 3.0 tightened defaults: fine-grained policies no longer cover sub-resources, and log access needs its own permission. Version 3.5 moved impersonation to beta, so syncs and other operations can run as a chosen service account instead of the controller’s own, and made ApplicationSets in any namespace stable.
Underneath, the controller is still powerful: in the 3.5.4 install.yaml, the argocd-application-controller ClusterRole allows every verb on every resource in every API group. Teams that cannot accept this use namespace-install.yaml with per-cluster credentials, or impersonation.
Flux has no separate RBAC. By default, kustomize-controller and helm-controller are bound to cluster-admin. Multi-tenancy comes from impersonation: each tenant’s Kustomization or HelmRelease names a service account, and Kubernetes RBAC limits what it can do. The multi-tenancy guide’s lockdown sets --no-cross-namespace-refs=true, --no-remote-bases=true and --default-service-account=default, so a tenant cannot use another namespace’s sources, pull remote bases or fall back to the controller’s rights. A tenant object then looks like this:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: web
namespace: team-web
spec:
interval: 10m
path: ./apps/web/overlays/prod
prune: true
serviceAccountName: web-deployer # RBAC limits this account
sourceRef:
kind: GitRepository
name: web
ignore: # Flux 2.9: leave HPA-owned field alone
- target: {kind: Deployment}
paths: ["/spec/replicas"]
Argo CD gives developers a familiar access model with SSO and per-application roles; Flux gives auditors one model, Kubernetes RBAC, that they already review. Neither is safe out of the box for many tenants.
Image automation
Flux has two optional controllers for this. image-reflector-controller scans registries and picks a tag by ImagePolicy, such as the newest semver. image-automation-controller commits it back to Git at lines marked like # {"$imagepolicy": "flux-system:podinfo"}. Since 2.9 it can sign those commits with SSH keys.
Argo CD Image Updater is a separate project in argoproj-labs, now at 1.3.0. It moved from annotations to an ImageUpdater CRD in 1.0, and its own docs say it is “under active development”. It writes back either by changing the Application parameters through the Kubernetes API or by committing to Git. The first is quicker, but the running version then no longer matches Git.
Notifications and user interface
Argo CD’s notifications controller uses triggers and templates, with services such as Slack, email, Teams and webhooks. Flux’s notification-controller sends events through Providers (Slack, Teams, PagerDuty, Alertmanager, GitHub and GitLab commit status, and more) and accepts inbound webhooks through Receivers, so a push triggers reconciliation at once.
The UI is the biggest visible difference. Argo CD’s web UI shows the resource tree, diffs, logs, sync buttons and, since 3.5, ApplicationSet previews. Flux core has only the CLI; the Flux site lists other UIs: the Flux Operator web UI from ControlPlane (with OIDC SSO mapped to Kubernetes RBAC), flux9s (a terminal UI whose GA post appeared on 5 October 2026), and plugins for Headlamp, Backstage and Freelens. Weave GitOps, the free UI Weaveworks offered, is listed in the past tense. Note that the Flux Operator is AGPLv3, unlike Flux itself.
Governance after Weaveworks
Weaveworks created Flux and coined the term GitOps, so its closure in early 2024 raised a fair worry. On 15 February 2024, ControlPlane announced it had hired core maintainers Stefan Prodan and Soule Ba, and launched an enterprise distribution with hardened, FIPS-compliant images and support. The CNCF announced further corporate support in March 2024. What followed is visible in the release pages: seven minor releases, from 2.3 in May 2024 to 2.9 in June 2026, roughly one every three to five months, with Helm v4 in 2.8 and a plugin system in 2.9. The current core maintainers list has nine names: three at ControlPlane, three independent, and one each at SUSE, NexHealth and Associmates. That is healthier than a one-company project, but ControlPlane is the centre of gravity, so keep watching it.
Argo CD’s maintainer base is wider. The Argo maintainers file names Argo CD leads at Intuit and Akuity, and approvers from Red Hat, Octopus Deploy, Akuity, Intuit, BlackRock and others. In February 2024, Octopus Deploy acquired Codefresh, another Argo maintainer company. A CNCF blog post on 30 September 2026 says planning for Argo CD 4.0 has begun.
Vendor-backed options, as listed by the projects and vendors:
Argo CD
Flux
Akuity Platform, from Argo CD’s creators
ControlPlane Enterprise for Flux CD
Red Hat OpenShift GitOps
Azure AKS and Azure Arc, through the microsoft.flux extension
Octopus Deploy, which now includes Codefresh
GitLab, AWS EKS Anywhere, Giant Swarm, VMware Tanzu, Nutanix
Amazon EKS Capability for Argo CD, running in the AWS control plane
Footprint and upgrades
The default Flux install asks for 350m CPU and 256 MiB of memory across four controllers, each capped at 1 CPU and 1 GiB. Argo CD’s manifests set no requests or limits, so its pods run as BestEffort until you add them. The repo server and application controller grow with repositories and applications, so size them from your own metrics.
Argo CD ships a minor release every three months after a seven-week release candidate freeze and patches only the three latest minors, so a team that upgrades once a year falls out of support. Since 3.3, the ApplicationSet CRD is too large for client-side apply, and upgrades must use server-side apply with --force-conflicts. Flux releases at least three minors a year, following Kubernetes, supports the last three, supports Kubernetes N-2, and allows upgrading from any 2.x to any 2.x. Either way, read the notes for every minor you cross.
A decision guide
Your situation
Reasonable first choice
Many developers need to see and sync their own apps
Argo CD with SSO and AppProjects
Platform team only, everything through Git and kubectl
Flux, or Argo CD Core
Clusters behind firewalls, edge or air-gapped sites
Flux in each cluster, or argocd-agent if you accept a 0.x project
One central view of hundreds of clusters
Argo CD hub with controller sharding, or argocd-agent
Helm-heavy estate with Helm runbooks
Flux helm-controller
Auditors want only Kubernetes RBAC to review
Flux with lockdown and impersonation
Image updates written back to Git out of the box
Flux image automation
Need vendor support and SLAs
Akuity, Red Hat, Octopus or AWS for Argo CD; ControlPlane, Azure or GitLab for Flux
A practical checklist
- Write down why you are choosing: developer UI, cluster count, network reach, audit or support.
- List Helm charts using hooks,
lookupor random values, and test them. - Decide hub or per-cluster before you design repositories.
- Decide pruning and self-heal per application, and write the decision down.
- Remove cluster-wide rights where you can: impersonation, namespace installs or Flux lockdown.
- Set resource requests and limits on every controller pod, Argo CD especially.
- Configure webhooks or Receivers so changes do not wait for the polling timer.
- Add drift ignore rules for fields owned by HPAs, cert-manager or webhooks.
- Plan upgrades on the release cadence, and use server-side apply for Argo CD.
- Rehearse a restore: rebuild a cluster from Git and time it.
Common mistakes
- Assuming Argo CD runs Helm. It renders charts; Helm commands do not see those releases.
- Leaving Argo CD auto-sync without prune, then wondering why deleted objects stay in the cluster.
- Fighting the HPA, in either tool, without ignore rules.
- Using Argo CD Image Updater’s API write-back, so the cluster and Git disagree.
- Running Flux multi-tenant without lockdown, so every tenant effectively has cluster-admin.
- Judging Flux by Weaveworks’ fate instead of by its current releases and maintainers.
Drill: what each one installs, offline
I kept this light on purpose: no cluster, no containers, no root access. On 7 October 2026, from about 6:19 to 6:28 PM IST, on a shared Linux VM, I downloaded the official release binaries of argocd 3.5.4, flux 2.9.6, kustomize 5.8.2 and helm 4.3.0 from GitHub and get.helm.sh, and all four matched their published SHA-256 checksums. I generated Flux manifests with flux install --export, fetched the four Argo CD 3.5.4 install manifests, and counted objects with a small Python script. Image sizes are sums of compressed linux/amd64 layers from the registry manifests.
What gets installed
Flux default
Flux with image and source-watcher controllers
Argo CD install.yaml
Argo CD core-install.yaml
Argo CD ha/install.yaml
Objects
32
43
59
34
70
Deployments and StatefulSets
4 + 0
7 + 0
6 + 1
3 + 1
6 + 2
CRDs
11
15
3
3
3
ServiceAccounts
4
7
7
4
8
ClusterRoles
3
3
3
1
3
Container images
4
7
3
2
4
Requests and limits set
All
All
None
None
None
Manifest size
269,825 bytes
344,464 bytes
1,917,766 bytes
1,882,880 bytes
1,969,264 bytes
Three things stood out. First, every Argo CD component uses one quay.io/argoproj/argocd:v3.5.4 image (221.3 MB compressed), plus Dex 2.45.1 (48.1 MB) and Redis 8.2.3 (27.5 MB). The four Flux controllers are separate images, 239.5 MB together, and you can skip the ones you do not use. Second, the ApplicationSet CRD alone is about 1.39 million bytes when serialised, more than five times the 262,144-byte annotation limit, which explains the server-side apply requirement. The largest Flux CRD, HelmRelease, is about 78,000 bytes. Third, even the HA manifest runs a single application controller replica; sharding is something you configure, not something you get.
On RBAC, both defaults are broad, in different ways. Argo CD’s controller ClusterRole is a full wildcard, including non-resource URLs, and argocd-server can get, patch and delete any resource. Flux binds kustomize-controller and helm-controller to cluster-admin. Of the manifests I checked, only Argo CD’s namespace-install.yaml comes without ClusterRoles.
Same overlay, two renderings
I built a tiny repository: a base Deployment and Service, and a prod overlay setting the namespace, three replicas, a new image tag and an environment variable ${cluster_name}, which a Flux Kustomization set to prod-mumbai-1 through postBuild.substitute.
kustomize build produced the expected objects with ${cluster_name} left as literal text, which is what Argo CD’s own Kustomize rendering would also give, since it only offers environment substitution for common annotations. flux build kustomization --dry-run replaced it with prod-mumbai-1 and added kustomize.toolkit.fluxcd.io/name and namespace labels to every object. A repository that depends on Flux substitution therefore needs changes before Argo CD can use it.
Argo CD RBAC without a server
The argocd admin settings rbac commands can test a policy file offline, though they refused to start without a kubeconfig; a dummy one pointing at an unused local port was enough. The policy I tested:
p, role:web-dev, applications, get, web/*, allow
p, role:web-dev, applications, sync, web/*, allow
p, role:web-dev, logs, get, web/*, allow
g, web-developers, role:web-dev
validate said the policy is valid. For web-developers, sync of web/frontend returned Yes, sync of payments/api No, delete No, logs Yes and exec No. This is a cheap CI test for RBAC changes.
Honest limits: no live cluster, so I measured no sync or reconcile timing, memory or CPU use. Image sizes are compressed downloads, not disk use. I did not test the Argo CD Helm chart, the Flux Operator, argocd-agent, Image Updater or notifications. Counts will change with each release. No command in the drill was blocked.
What to unlearn and re-learn
- Unlearn “GitOps tools are interchangeable”. Re-learn that Argo CD is a service with its own API and RBAC, and Flux is a set of controllers on Kubernetes RBAC.
- Unlearn “Argo CD deploys Helm charts”. Re-learn that it renders them, and plan hooks and runbooks to match.
- Unlearn “Flux died with Weaveworks”. Re-learn to judge a project by its recent releases and maintainer list.
- Unlearn “the defaults are production settings”. Re-learn that both install broad cluster rights and that Argo CD sets no resource limits.
Revisit your GitOps controller before you scale or migrate
The Pune team does not need a winner; it needs a clear reason. If developers must see and act on their own applications, Argo CD’s UI and RBAC are worth running. If the platform team wants controllers inside each cluster under Kubernetes RBAC, Flux is the smaller tool. Learn how your chosen tool really syncs, renders Helm and handles drift. Unlearn the habits the other tool taught you. Re-learn tenancy and upgrades on its terms. Practise with a drill like this one and a staging cluster rebuilt from Git. Then apply what you learn to your repositories, RBAC and runbooks, before the next twenty clusters make the choice harder.
Sources
- Argo CD repository, 3.5.4 release, 3.5.0 release, 3.6.0-rc2 release, 3.0.0 release, 2.0.0 release, v0.1.0 release, LICENSE
- Argo CD docs: architecture, installation, Argo CD Core, high availability, argocd-cm reference, release process and cadence
- Argo CD docs: automated sync, sync options, diffing, Helm, Kustomize, OCI sources
- Argo CD docs: RBAC, user management and SSO, applications in any namespace, ApplicationSet, notifications, notification services
- Argo CD upgrade notes: 2.14 to 3.0, 3.2 to 3.3, 3.4 to 3.5
- Argo blog: Argo CD v3.5 release candidate, Argo CD v3.0 release candidate, Introducing Argo CD (2018), Applatix joins Intuit
- Argo maintainers, Argo CD Image Updater docs, update methods, Image Updater repository, argocd-agent repository
- CNCF: Argo, Argo graduation announcement, ArgoCon North America 2026 and Argo CD 4.0
- Flux repository, 2.9.6 release, 2.9.0 release, 2.8.0 release, 2.0.0 release, LICENSE, core maintainers
- Flux docs: components, concepts, Kustomization API, HelmRelease API, GitRepository API, OCIRepository API
- Flux docs: multi-tenancy lockdown, security, sharding, vertical scaling, image updates, alerts, notification providers, receivers, FAQ
- Flux releases and support policy, upgrade guide, support, ecosystem
- Flux blog: Flux 2.9 GA, Flux 2.8 GA, Flux turns 10, Flux 2.0 GA, corporate support in 2024
- CNCF: Flux, Flux graduation announcement, FluxCD gains new corporate support (March 2024)
- ControlPlane: backing Flux by employing maintainers, Enterprise for Flux CD, Flux Operator repository, Flux Operator web UI
- Octopus Deploy acquires Codefresh, Akuity, Red Hat OpenShift GitOps, Amazon EKS: Argo CD capability, Microsoft: GitOps with Flux v2 for AKS and Azure Arc, GitLab: GitOps with Flux
- Rancher Fleet docs, Fleet 0.16.2 release, Sveltos docs, Sveltos 1.16.0 release
- Kustomize 5.8.2 release, Helm releases
Releted Posts
Ingress NGINX retirement: revisit your Kubernetes ingress before you migrate
A platform team plans its Kubernetes 1.37 upgrade for the next sprint. The cluster checklist is green, except one line nobody owns: the ingress-nginx Helm chart, pinned at 4.
Read moreVault and OpenBao: revisit your secrets manager before you renew or migrate
A platform team runs a three-node Vault Community cluster for about sixty services. In one week, a product group asks for its own isolated tenant, which in Vault means namespaces, an Enterprise feature, and finance asks whether the Enterprise quote is really needed.
Read morePrometheus long-term storage: revisit Thanos, Mimir and VictoriaMetrics before you scale
A platform team runs two Prometheus servers per cluster as an HA pair, with 15 days of local retention. In one quarter, three requests arrive: the SRE lead wants a year of history for capacity planning, a product team adds a customer_id label to a request metric, and the auditors ask what happens to metrics when a disk dies.
Read more