Managing Amazon EKS at Fleet Scale

GitOps at Fleet Scale: Hundreds of EKS Clusters Without Losing Control

A deeper, more current companion to the fleet-management series: how to run dozens or hundreds of EKS clusters through GitOps without losing control — Argo CD’s single pane versus Flux’s distributed pull, the GitOps bridge that wires them to your IaC, the scaling ceilings that actually bite, and the December 2025 managed EKS Capability that changes the build-versus-buy math.

The bottom line

There's no universal winner — anyone who says otherwise is selling something. At a few hundred EKS clusters the decision reduces to one axis: a centralized single pane of glass versus distributed autonomy.

Argo CD hub-and-spoke gives you templated fleet rollouts and one dashboard, but it concentrates blast radius in a central control plane and hits UI and reconciliation limits that force you to shard the application controller. Flux's one-controller-per-cluster model is more resilient and the honest answer for edge and air-gapped clusters, but you lose the single pane. Most large fleets converge on a hybrid: Flux for the platform layer on every cluster, one central Argo CD for application releases, wired together by the GitOps bridge. And since December 2025, AWS will run the Argo hub for you as a managed EKS Capability, changing the build-versus-buy math for the control plane.

  • The axis: centralized (Argo hub-and-spoke, one dashboard, concentrated risk) vs distributed (Flux per cluster, resilient, no single pane).
  • Argo scales, but you work for it: benchmarks reach 10,000 apps / 97 clusters (AWS) and 50,000 apps / 500 clusters (CNOE) — only with controller sharding and QPS tuning. The UI, not the controller, is the softer ceiling.
  • Flux trades the dashboard for resilience: each cluster keeps reconciling if the rest of the fleet burns; no central plane that must reach every cluster's API.
  • The GitOps bridge lets Terraform hand cluster metadata (IAM roles, endpoints) to Argo via a cluster Secret — without Terraform and GitOps fighting over cluster state.
  • Hybrid is where most large fleets land: Flux for infra, Argo for apps, with a hard repo boundary so they never write the same directory.
  • New in 2026: AWS's managed EKS Capability for Argo CD runs the hub outside your clusters and handles cross-account/cross-region and private-endpoint reach.

What fleet GitOps gives you

  • One source of truth — the repo, not a laptop — with drift caught and self-healed on every cluster.
  • One change fans out to N clusters through an ApplicationSet cluster generator keyed off labels.
  • A managed path now exists: AWS runs the Argo hub for you as the EKS Capability.

What it won't do for free

  • There's no universal winner — centralized single pane and distributed autonomy are a genuine trade.
  • Argo reaches tens of thousands of apps only with controller sharding and QPS tuning; the UI drags first.
  • A central hub is a real blast radius — size it like production or accept a fleet-wide freeze on outage.

What actually breaks at fleet scale — Three clusters and three hundred are not the same problem

GitOps at three clusters is solved: point one Argo CD or Flux at a repo and move on. "Fleet scale" gets its own playbook because three things stop being free past a few dozen clusters.

Figure 1 · What breaks at fleet scale Past a few dozen clusters, three things stop being free: 1 Automatic onboarding A new cluster must join by having the right label — not by a human editing YAML. Editing per cluster is a backlog, not a fleet. 2 Reconcile cost One controller diffing Git against hundreds of live clusters is real CPU, API traffic, and sync latency. 3 Blast radius Not "does it deploy" but "how many clusters go down when it misbehaves" — the question that splits the centralized vs distributed camps.
Takeaway: the reconcile point is where Argo CD needs sharding and Flux spreads load by design; the blast-radius point is what splits the two camps this guide compares.

The centralized bet — Argo CD hub-and-spoke — one dashboard drives the whole fleet

Hub-and-spoke puts one Argo CD instance — the hub — in charge of many workload clusters, the spokes. The hub holds one Kubernetes Secret per spoke, and Argo's ApplicationSet cluster generator reads those Secrets to produce one Argo Application per matching cluster.1 That's what makes onboarding automatic: drop a labeled Secret in and the controller deploys everything for that cluster, no further edits.

Figure 2 · Argo CD hub-and-spoke Hub cluster · Argo CD Application controller (shardable) Repo-server API / Web UI ApplicationSet · cluster generator Cluster Secrets — one per spoke, labeled: prod-eu prod-us staging e.g. tier=canary — a label selector targets a group; generator reads Secrets, fans Apps. Spoke EKS cluster 1 Argo Application Spoke EKS cluster 1 Argo Application Spoke EKS cluster 1 Argo Application + N more spokes one Application per matching spoke
Argo CD / centralized hub Flux / per-cluster (distributed) Terraform / cloud infra & metadata workload / spoke cluster
Takeaway: create a labeled Secret and the cluster generator fans one templated Application to every matching spoke — onboarding is "exist with the right label." Colors above are the legend for every diagram in this guide.

Label selectors are how you carve the fleet into groups

Argo CD has no native "cluster group" object, so you build groups out of labels on the cluster Secret, and an ApplicationSet's cluster generator uses a label selector to hit only matching clusters.1 Label a batch tier: canary and one ApplicationSet deploys just to them — a tiered-rollout primitive, straight from a selector. Need per-cluster overlays? Nest a Git generator (enumerating overlay paths) and the cluster generator inside a Matrix generator, and you get the Cartesian product of overlays × clusters.1

App-of-apps or ApplicationSet — you'll likely use both

Two patterns get conflated. The Argo project steers fleet operators toward the ApplicationSet cluster generator for most bootstrapping, but many teams use both — app-of-apps for the first bootstrap, then ApplicationSets for team self-service on top.2

PatternWhat it isBest when
App-of-appsAn Argo Application whose children are themselves Applications — full manual controlEach app is different (different repo, chart, config)
ApplicationSetA controller that generates Applications from a generator + templateThe same app across many clusters

Wiring the fleet without Terraform fighting you — The GitOps bridge pattern

Here's the problem the hub-and-spoke diagram hides. Cluster add-ons need cloud metadata Terraform owns but Argo CD wants at install time — the IAM role ARN for an IRSA-backed controller, a load balancer's DNS name, the cluster's API endpoint. The tempting fix, running the Helm charts through Terraform's Kubernetes provider, puts Terraform and GitOps in a fight over live cluster state, and you get conflicts.3 The GitOps bridge settles it cleanly: Terraform writes the metadata as labels and annotations on the Argo CD cluster Secret, and stops there.3

Figure 3 · The GitOps bridge Terraform Provisions VPC · EKS · IAM Owns cloud resources Never runs workloads Argo CD cluster Secret (labels / annotations on hub) roleARN clusterName / endpoint awsAuthConfig Spoke cluster Add-on Helm charts deployed by the hub via assumed roleARN writes metadata reads → Helm values Terraform owns cloud resources · GitOps owns cluster state · the Secret is the one narrow, declarative handoff.
Takeaway: the cluster Secret is the only bridge — Terraform writes cloud metadata into it and never touches workloads, so the two systems stop fighting over live cluster state.

AWS's EKS Blueprints reference implementation makes this concrete. Each spoke Secret carries an awsAuthConfig block with the spoke's clusterName and a roleARN the hub assumes to deploy into that spoke — so the hub reaches every spoke by IAM role assumption, with no long-lived credentials copied around.4 ApplicationSets for add-ons and workloads then generate a per-spoke app-of-apps (workloads-${env}) for each registered cluster.4

Where the single control plane starts to hurt — Argo CD's UI and reconcile limits — and how sharding buys headroom

The centralized model has a ceiling, and it's worth knowing exactly where — the honest answer is "further than you'd guess, but not for free."

The controller scales — with sharding and tuning

Two independent benchmarks put real numbers on it. AWS drove a single Argo CD to 10,000 applications across 97 clusters,5 and CNOE pushed to 50,000 applications across 500 clusters on three m5.2xlarge nodes.6 The chart shows what sharding the controller and raising client QPS did to full-sync time.

Figure 4 · Argo CD sync-time benchmarks Full-sync time (minutes) 0 10 20 30 40 50 53 min 8m30s 9 min 22 min AWS · 10k apps / 97 clusters · default AWS · same, 10 shards + QPS tuning CNOE · 10k apps / 100 clusters CNOE · 50k apps / 500 clusters default settings sharded + QPS-tuned
Takeaway: sharding plus QPS tuning turns a 53-minute sync into roughly 8m30s — and the same tuned setup reaches 50,000 apps across 500 clusters at about 22 minutes.

The tuning lessons from those runs are specific and reusable:

Worth noting: the official docs set no hard per-instance limit — the guidance is entirely benchmark-driven, with tuning recommendations calibrated "for 1000 applications."7

The UI is the softer ceiling

The controller shards; the web UI doesn't, not as gracefully. It starts to drag past about 1,000 applications per instance, and community reports bear that out: the UI goes sluggish at 1,500+ apps, and one instance with roughly 8,000 apps from ~2,000 ApplicationSets took about 35 seconds just to load the application list.8 The cause is architectural — the server fetches every application, then filters by RBAC, so the cost grows with total app count no matter what you're viewing; server-side pagination is the fix maintainers are working toward.8

Label this as a practitioner estimate, not a hard fact. The rule of thumb is to keep each Argo CD instance to roughly 1,000–2,000 applications and run multiple instances beyond that.9 The vendor Akuity has demonstrated a single instance handling 1,000 clusters and 50,000 apps.10 Neither is an official ceiling — treat both as datapoints. AWS's own guidance frames Argo's scalability as "limited by the web UI's data-fetching rate."11

When the hub goes down, what goes with it — Central control-plane blast radius

Everything above is the cost of success. The cost of failure is the real argument against centralizing. The hub reaches into every spoke's Kubernetes API to reconcile it — that's the single pane, and what makes the hub a single point of failure holding one very powerful set of credentials with write access to the whole fleet.12 Compromise or wedge it, and the whole fleet's delivery path goes down with it.

That's not a reason to never centralize. Running clusters keep running — a dead hub doesn't delete your workloads. But it freezes all deployment, drift correction, and self-heal across the fleet at once — exactly the shared fate a distributed model refuses to accept.

The distributed bet — Flux — one controller per cluster, no shared fate

Flux flips the topology. In the standalone model each cluster runs its own Flux controllers, pulling its own slice of a fleet repo directly. As Flux maintainer Stefan Prodan puts it, this "minimizes attack surface and blast radius" and lets clusters "function autonomously even during outages."12 There's no central plane holding fleet-wide credentials, and no hub whose death freezes the rest.

Figure 5 · Flux distributed pull Fleet Git repo clusters/prod-eu · prod-us · staging each cluster pulls only its own path EKS cluster (prod-eu) source-controller kustomize-controller helm-controller EKS cluster (prod-us) source-controller kustomize-controller helm-controller EKS cluster (staging) source-controller kustomize-controller helm-controller pull pull No central control plane · no fleet-wide credentials · no single dashboard
Takeaway: each cluster pulls and reconciles on its own, so one keeps running if the rest of the fleet burns — the price is that "is the whole fleet in sync?" becomes a metrics question, not one dashboard.

The price is exactly what centralization was buying: the single pane. Each cluster is bootstrapped and watched on its own, so fleet-wide sync status comes from aggregated metrics, not one dashboard.12 Flux can run hub-and-spoke too — a central Flux reaching into spoke API servers — but that hands back the single point of failure and networking complexity you distributed to avoid.12

Edge and air-gapped clusters make the choice for you

For edge, IoT, and air-gapped or classified clusters, distributed isn't a preference — it's close to a requirement. Argo's central control plane must reach every managed cluster's Kubernetes API, exactly what a strict air-gap forbids. Flux's per-cluster controller pulls locally, needs no central API server, and travels lighter on resource-constrained nodes.13 AWS's prescriptive guidance points to Flux for "edge computing or IoT scenarios where resources might be constrained."11

How you lay out the repo for a fleet — Structure is the part people underestimate

Both tools live or die by repo structure. The Flux fleet repository splits into three top-level trees.14

Figure 6 · Fleet repo structure fleet-repo/ clusters/ prod-eu · prod-us · staging one dir per cluster — its Flux config + what to reconcile infrastructure/ base + per-environment ingress, policies, controllers — applied with admin privileges tenants/ namespaces · RBAC · Flux CRs per team — reconciled under impersonated SAs (can't escape)
Takeaway: three trees split the fleet by privilege — admin-level platform config, per-cluster reconciliation, and tenant workloads fenced behind impersonated service accounts so a team can't escape its boundary.

The pattern that scales: onboard a new cluster by wiring the Flux Terraform provider into the cluster-provisioning pipeline, so the cluster bootstraps itself against its clusters/<name> path as it's created.12 The Argo equivalent is the GitOps bridge — the cluster registers by having a labeled Secret, and the ApplicationSet cluster generator takes it from there.

Shipping safely across the fleet — Progressive delivery and drift correction

Drift detection and self-heal — the everyday guarantee

Both tools continuously reconcile Git against live state. In Argo CD, automated sync with prune: true and selfHeal: true reverts manual changes back to Git (retried after a 5-second self-heal timeout) and prunes anything you deleted from Git.15 That's the real GitOps guarantee at fleet scale — not "we deployed it once" but "the cluster is continuously dragged back to the repo," on every one of the hundreds of clusters, with nobody watching.

Progressive delivery — Argo Rollouts vs Flagger

Neither Argo CD nor Flux does canary analysis itself; each pairs with a progressive-delivery controller, and the choice usually follows the ecosystem you already picked.

DimensionArgo RolloutsFlagger
Manifest modelReplaces Deployment with a Rollout custom resourceKeeps standard Deployment; zero manifest changes
Control styleExplicit, ordered steps with manual approval gatesDeclarative analysis spec; auto-progresses by step weight
Ecosystem fitArgo CD (health checks + UI extension built in)Flux ecosystem
StrategiesBoth: canary, blue-green, A/B

The practical read: if your fleet runs Argo CD, reach for Argo Rollouts and get the integrated UI; if it runs Flux, Flagger's zero-touch, metric-driven promotion is the natural fit.16

The answer most large fleets reach — The hybrid — Flux for infra, Argo for apps

Once you've felt both sides, the hybrid stops looking like a compromise and starts looking like the point: Flux runs inside every cluster for the platform layer — resilient, distributed, no shared fate for the infrastructure everything else leans on — while one central Argo CD owns application releases, giving developers the dashboard and app-centric view they want.17 AWS's prescriptive guidance maps onto the split: Argo CD for visual, app-centric, multi-cluster management with enterprise RBAC and SSO; Flux for lightweight, strongly multi-tenant, IaC-driven platform management.11

Figure 7 · The hybrid model Central Argo CD (hub) app releases + one dashboard EKS cluster Flux · platform layer add-ons, controllers, policies app layer reconciled by central Argo EKS cluster Flux · platform layer add-ons, controllers, policies app layer reconciled by central Argo EKS cluster Flux · platform layer add-ons, controllers, policies app layer reconciled by central Argo Hard repo boundary: infra paths → Flux · app paths → Argo — the two never write the same directory
Takeaway: Flux (distributed, per-cluster) owns the platform layer and Argo (central, one dashboard) owns app releases — each does the job it's best at, kept safe by a hard repo ownership boundary.
The one guardrail that makes hybrid safe: split the repositories so Argo CD never writes a directory Flux manages, and vice versa. Two GitOps controllers fighting over the same resource is a self-inflicted outage. With a hard ownership boundary — infra paths for Flux, app paths for Argo — it runs cleanly.17

What AWS just changed — The managed EKS Capability for Argo CD (December 2025)

The build-versus-buy math for the Argo hub shifted in late 2025. AWS launched the Amazon EKS Capability for Argo CD: a fully managed Argo CD running in AWS-managed service accounts outside your clusters, with AWS handling scaling, upgrades, inter-cluster communication, and token refresh.18 It takes over exactly the hardest parts of self-managed hub-and-spoke:

It's still Argo CD — ApplicationSets, the hub-and-spoke topology, the single pane — so everything above about UI limits and blast radius still applies conceptually. What changes is you no longer operate, scale, or patch the hub yourself. If you're standing up fleet GitOps on EKS in 2026, this is the first option to price out before you self-host.

Choose this when — Decision thresholds, not vibes

Figure 8 · Decision tree Hundreds of EKS clusters, need GitOps Edge, air-gapped, or resource-constrained — must survive independently? Need one dashboard + app-centric self-service across the fleet? Strong multi-tenancy + IaC platform, and app teams who want a UI? yes Flux — one controller per cluster distributed, no shared fate yes Operate the hub yourself? no Managed EKS Capability for Argo CD yes Self-managed hub-spoke shard the controller past ~1,000 apps yes Hybrid: Flux infra + central Argo apps hard repo boundary
Takeaway: air-gap or survive-alone needs push you to Flux; a single-pane need points to Argo (managed if you'd rather not run the hub); strong multi-tenancy plus developer UX lands on the hybrid.
If your situation is…Lean toward
You want one dashboard, app-centric workflows, and developer self-service across the fleetArgo CD hub-and-spoke
You're on EKS and want to skip operating the hub entirelyManaged EKS Capability for Argo CD
Clusters are at the edge, air-gapped, resource-constrained, or must survive independentlyFlux, one controller per cluster
Blast radius / no-shared-fate is your top constraintFlux distributed (or Flux hybrid)
You have strong multi-tenancy and IaC-heavy platform needs plus app teams who want a UIHybrid: Flux infra + Argo apps
A single Argo instance is creeping past ~1,000–2,000 apps and the UI is draggingShard the controller and/or split into multiple instances

Common pitfalls — The failures that actually bite fleets

Sources

  1. Argo CD docs — ApplicationSet Cluster Generator (label selectors, cluster Secrets, Matrix generator)
  2. Argo CD Discussion #11892 — Bootstrapping: ApplicationSets vs App-of-apps; Argo CD docs — Cluster Bootstrapping
  3. gitops-bridge-dev/gitops-bridge — the GitOps bridge pattern (Terraform metadata into the cluster Secret)
  4. AWS EKS Blueprints — Multi-Cluster Hub & Spoke Argo CD (awsAuthConfig, roleARN, per-spoke ApplicationSets)
  5. AWS Open Source Blog — Argo CD Application Controller Scalability Testing on Amazon EKS (10k apps / 97 clusters; sharding; QPS), Sep 13 2023
  6. CNOE — Argo CD Benchmarking: 50k apps / 500 clusters, sharding algorithms compared, Nov 21 2023
  7. Argo CD docs — High Availability (sharding methods, controller replicas, processor/QPS tuning; no hard per-instance limit)
  8. Argo CD Discussion #8446 — UI slow with 1.5k+ applications (fetch-all-then-RBAC-filter root cause; pagination)
  9. OneUptime — Argo CD single vs multiple instances (practitioner rule of thumb: ~1,000–2,000 apps/instance) — practitioner estimate
  10. Akuity — Argo CD scalability (1,000 clusters / 50,000 apps) — vendor claim
  11. AWS Prescriptive Guidance — Argo CD and Flux use cases (feature comparison, when to choose each)
  12. Stefan Prodan (Flux maintainer) — FluxCD Multi-Cluster Architecture (standalone vs hub-spoke, blast radius, fleet repo, Terraform provider onboarding), May 22 2024
  13. OneUptime — Flux CD vs Argo CD for air-gapped environments (central plane must reach cluster APIs) — practitioner, architecturally corroborated
  14. Flux docs — Ways of structuring your repositories; fluxcd/flux2-multi-tenancy — fleet repo layout (clusters / infrastructure / tenants)
  15. Argo CD docs — Automated Sync Policy (prune, selfHeal, self-heal timeout)
  16. Flagger vs Argo Rollouts comparison; Buoyant — Flagger vs Argo Rollouts — practitioner, triangulated
  17. Pelotech — Argo CD vs Flux (hybrid: Flux for infra + central Argo for apps; repo ownership boundary)
  18. AWS Containers Blog — Deep dive: streamlining GitOps with the Amazon EKS Capability for Argo CD (managed hub, cross-account/region, private endpoints), Dec 18 2025