In 2026, anyone still deploying Kubernetes applications via classic push pipelines with kubectl-apply steps is fighting three recurring problems: nobody knows exactly what is running in the cluster, manual hotfixes create invisible drift, and rollbacks take longer than the incident itself. GitOps is the answer that has established itself across the industry since around 2019 and has since become a CNCF-recognized operational standard. The core idea is radically simple: Git is the single source of truth for the desired cluster state, and a controller inside the cluster continuously reconciles the actual state with the Git content. Two tools dominate the market — ArgoCD and Flux, both CNCF-graduated and battle-tested in thousands of organizations. This article shows how GitOps can be sensibly set up with both tools in a mid-market context, how they differ, what repo structure holds up over time, and how secrets, multi-cluster, and Progressive Delivery fit into the picture. For context within the broader platform, see our Cloud & DevOps Guide for Mid-Market Companies.
What GitOps Is — Pull Instead of Push, Git as the Single Source of Truth
GitOps is not a tool but an operational model. It rests on four principles that the CNCF OpenGitOps working group formally described in 2022: the desired system behavior is declared declaratively, the desired state is versioned and immutable, changes are applied automatically, and software agents continuously reconcile the actual state with the desired state. These four principles sound abstract; their operational consequence is concrete: nobody reaches into the cluster directly with kubectl any more, every change is a pull request against a Git repository, which automatically takes effect in the cluster after merge.
The key technical difference from classic CD is the pull model. In a typical Jenkins or GitHub Actions pipeline, the build server pushes manifests into the cluster at the end of a job — meaning the build server needs cluster credentials, is reachable from outside the cluster, and acts as both CI system and deploy agent simultaneously. In the pull model, the GitOps controller (ArgoCD or Flux) runs inside the cluster, watches the Git repo, and actively fetches changes. The cluster no longer needs incoming cluster credentials for external systems, the attack surface shrinks considerably, and the separation between CI (code build, tests, container image build) and CD (cluster sync) becomes clean.
Operationally this means: the CI system ends by pushing a new container image to a registry and updating the config repo with the new image version (either via pull request or via an image-updater component). From that point the GitOps controller takes over. Organizations that take GitOps seriously no longer have human write access to their cluster — all changes happen through pull requests against the config repo, with review, with audit log, with rationale in the commit message body.
Benefits — Audit, Reproducibility, Rollback
Three operational properties make GitOps so attractive for mid-market companies. First, auditability: every change to the production system is a Git commit with author, timestamp, reviewer, and rationale. During a GDPR or ISO 27001 audit, the question "Who changed this configuration on 14 March?" is answered in seconds, without correlating logs from three different systems. That is relevant not only for external audits but also accelerates every internal forensic investigation.
Second, reproducibility: because the desired state lives entirely in Git, a cluster can be reconstructed from the repo at any time. In a disaster recovery scenario, all that is needed is to provision a new cluster and apply the bootstrap manifest — the rest runs automatically. Combined with our article on zero-downtime deployment, this yields an operational setup where cluster losses are addressed in hours rather than days.
Third, rollback speed. In the GitOps model, a rollback is a git revert on the problematic config commit, followed by an automatic sync. The entire operation takes two to five minutes in practice, is fully auditable, and requires no manual kubectl intervention. All three properties pay off immediately even in a single-cluster setup, and the value grows with each additional environment.
ArgoCD — Architecture, Applications, ApplicationSets, Sync Waves
ArgoCD is currently the most widely adopted GitOps controller, originally developed at Intuit and promoted to CNCF Graduated status in 2022. Architecturally, ArgoCD consists of five main components: the API server (the web UI and gRPC API), the repository server (clones and caches Git repos), the application controller (compares desired and actual state and syncs), the Redis cache, and the web UI. All components run in the cluster and only need outbound access to the Git repo and the container registry.
The central resource is the Application — a custom resource that defines which Git repo, which path, and which target cluster together constitute an application. With more than a handful of applications this quickly becomes unwieldy, which is why the app-of-apps pattern exists: a root Application that watches a folder in the repo containing further Application manifests. This allows the entire cluster content to be installed declaratively in a single bootstrap step.
For scaling setups there is the ApplicationSet resource, which combines a template with a generator. The generator can be a list, a Git directory, a cluster set, or a pull request. This enables patterns such as "for every cluster in the Argo directory, automatically create a platform-services Application" or "for every branch in the feature repo, automatically create a preview environment." For multi-cluster and multi-tenant setups, ApplicationSet is the decisive tool.
Sync waves are ArgoCD's answer to dependencies: manifests can be annotated with an argocd.argoproj.io/sync-wave annotation, and ArgoCD applies them in ascending wave order. This matters when namespaces, CRDs, and operators must be installed before the applications that use them. Combined with sync hooks (PreSync, Sync, PostSync, SyncFail), a declarative dependency model emerges that maps even complex rollouts cleanly.
Flux — Architecture, Sources, Kustomizations, HelmReleases
Flux originated at Weaveworks (which coined the term GitOps in 2017) and is today an independent CNCF Graduated project. Architecturally, Flux differs significantly from ArgoCD: instead of a monolithic application with a UI, Flux consists of four independent controllers (Source Controller, Kustomize Controller, Helm Controller, Notification Controller), each responsible for a clearly scoped aspect. There is no built-in UI — status queries happen via the flux CLI or through the third-party Weave GitOps Dashboard.
The central resources are GitRepository and HelmRepository (sources that the Source Controller clones and checks for new versions), Kustomization (applied by the Kustomize Controller), and HelmRelease (installed and upgraded by the Helm Controller). This separation is conceptually clean and makes Flux highly testable — each controller is independently deployable and finely integrated into the cluster RBAC.
Flux is designed for multi-cluster setups from the ground up: the bootstrap command (flux bootstrap) provisions a cluster with all Flux components plus the reference to the config repo in one step, after which the cluster manages itself from the repo. For setups with identical configuration across many clusters (such as edge setups or multi-region production), Flux is often the more efficient choice thanks to its lean architecture and GitOps-native bootstrap routine.
ArgoCD vs Flux — Head-to-Head Comparison
Both tools are production-grade and cover the core GitOps functionality completely. The differences lie in the operational philosophy, UI availability, and multi-cluster bootstrap routine. The following table summarizes the key differentiators:
| Criterion | ArgoCD | Flux |
|---|---|---|
| Web UI | Fully featured and built-in; sync status and rollbacks are clickable | No built-in UI; optional Weave GitOps Dashboard |
| Architecture | Monolithic (API server, repo server, application controller) | Component-based (Source, Kustomize, Helm, Notification) |
| Multi-cluster | Hub-and-spoke (one ArgoCD manages multiple clusters) | Cluster-local; each cluster manages itself |
| Multi-tenancy | AppProjects, fine-grained RBAC, SSO integration | Namespace-based, Kubernetes RBAC |
| Helm support | Render mode; charts are converted to manifests | Native HelmRelease with a full Helm release lifecycle |
| Image updates | Argo Image Updater (add-on) | Image Reflector and Image Automation built in |
| Learning curve | UI makes onboarding easier | CLI-oriented; slightly steeper |
Practical recommendation from our consulting projects: teams with a platform staff of one to two people, where application teams need to view sync status and rollbacks themselves, are clearly better served by ArgoCD. Teams with a GitOps-experienced platform staff deploying many clusters with identical configurations and valuing the component model as an advantage are better served by Flux. In hybrid setups there are also configurations where ArgoCD handles the application layer and Flux manages the platform layer.
Evaluate Your GitOps Setup Together
Considering your first GitOps deployment or consolidating an existing setup? We offer a free 30-minute initial consultation — we assess your current CD maturity, recommend ArgoCD or Flux with reasoning, and sketch a realistic migration roadmap.
Request a Free GitOps ConsultationRepo Structure — App-of-Apps, Monorepo, Env Branching
The repo structure largely determines whether a GitOps setup is still maintainable six months down the road. Three patterns have established themselves, and not every one fits every organization. The following overview shows the key decision axes:
- App code and config kept separateThe application source code lives in an application repo (with Dockerfile, Helm chart template, tests); the deployed manifests live in a separate config repo that only the GitOps controller watches. This separation is the most important structural decision — it prevents every code commit from automatically triggering a deploy, and keeps permissions clear (application developers write to the app repo; the platform team reviews the config repo).
- Config repo as a monorepoAll applications, platform services, and cluster configurations are managed centrally in the config repo. For mid-market setups with up to around 100 applications, this is the preferred approach — shared reviews, cross-cutting refactoring, and a consistent PR workflow are far easier than with one repo per application.
- App-of-apps or Kustomization hierarchyA root Application (ArgoCD) or root Kustomization (Flux) points to a directory containing further Application or Kustomization definitions. This allows a cluster to be fully provisioned in a single bootstrap step — no 50 manual kubectl-applys, but one declarative entry point.
- Environments as folders, not branchesDev, staging, and prod are their own folders with Kustomize overlays or Helm values, not their own branches. Using branches as environment separators is a common anti-pattern — they create hard-to-resolve drift because cherry-picks and merges between branches never stay clean.
- Promotion via pull requestA new image version lands first in the dev overlay; an automated PR then updates the staging overlay; after tests pass, the prod overlay PR is approved manually. Every promotion step is thus a traceable Git operation with reviewer and rationale.
For connecting to the upstream CI, see our article on building a CI/CD pipeline — the build steps end with a container push and a config repo update, after which the GitOps controller takes over. This clean separation is the most important architectural lever of the entire approach.
Secrets — SealedSecrets, SOPS, External Secrets, Vault
Plaintext secrets do not belong in Git; encrypted secrets absolutely do. Four patterns are established in GitOps practice, differing in complexity and strategic maturity. The following table categorizes the options:
| Solution | Encryption | Suitable for | Reepa recommendation |
|---|---|---|---|
| SealedSecrets (Bitnami) | Asymmetric, cluster-specific public key | Single clusters, easy entry point | Getting started; small and mid-market up to 3 clusters |
| Mozilla SOPS | age, GPG, or cloud KMS (AWS/GCP/Azure) | Multi-cluster, no extra controller needed | Mid-market when cloud KMS is already in place |
| External Secrets Operator | Git contains only references; secrets live in Vault/cloud | Setups with a central secret store | Strategically strongest solution for multiple clusters |
| HashiCorp Vault direct | Vault Agent or CSI driver | High compliance requirements | Banks, insurers, regulated industries |
For most mid-market setups we recommend starting with SealedSecrets or SOPS and transitioning to the External Secrets Operator with Vault once more than two or three clusters are in play. SealedSecrets has a disadvantage that is often underestimated in practice: the encryption key is cluster-specific, and disaster recovery absolutely requires a backup of that key. Anyone who forgets this will find themselves in a recovery situation with a repo full of secrets that nobody can decrypt.
Progressive Delivery — Flagger and Argo Rollouts
GitOps provides the rollout mechanism but says nothing about how a rollout should proceed. Anyone who needs canary releases, blue-green deployments, or feature-flag-driven promotions adds a Progressive Delivery layer on top of GitOps. Two tools dominate: Argo Rollouts (typically combined with ArgoCD) and Flagger (typically combined with Flux, originally from Weaveworks).
Argo Rollouts replaces the standard Deployment object with its own Rollout resource that supports canary steps, auto-promote conditions, and analysis runs based on Prometheus metrics. Flagger operates as an operator that annotates existing Deployments and maps the canary progression via service mesh tools such as Istio, Linkerd, or the traffic-weighting mechanism of the NGINX Ingress Controller. Both tools automatically analyze metrics (error rate, latency, custom SLIs) during a canary step and abort the rollout if values move outside the green zone.
For mid-market setups, Progressive Delivery is often the second step after the initial GitOps adoption. But anyone deploying applications with high business risk (online shops, booking systems, payment functions) should plan for Progressive Delivery from the start — the investment pays back with the first prevented production incident.
Multi-Cluster and Multi-Environment
As soon as more than one cluster is involved, the question arises whether a central GitOps controller manages all clusters (hub-and-spoke) or whether each cluster manages itself from the repo (cluster-local). ArgoCD is classically a hub-and-spoke tool: a central ArgoCD cluster registers target clusters and syncs applications into them. This simplifies reporting (one UI for all clusters) but creates a central point of failure and requires cluster credentials to be held centrally.
Flux follows the cluster-local model: each cluster has its own Flux stack and watches the shared config repo (typically with a cluster-specific path). This is more resilient (failure of one cluster does not affect the others), but reporting must be aggregated via external tooling (Grafana, Weave GitOps Dashboard). For setups spanning multiple production regions, the cluster-local model is architecturally cleaner.
For environment separation we recommend physically separate clusters for production and everything else, and logically separate namespaces for dev and staging in the same non-production cluster. Running production workloads and test workloads in the same cluster risks noisy-neighbor effects and security collateral damage that, while more quickly remediable in the GitOps model, are no less painful. For more on this, see our Kubernetes guide for mid-market companies.
Migrating from Classic CD
Migration from a Jenkins- or GitHub Actions-based push CD typically proceeds in four phases over eight to sixteen weeks. Phase one is platform preparation: ArgoCD or Flux is installed in the first cluster, a config repo is created, and platform services (Ingress, Cert-Manager, Monitoring) are migrated as the first applications. This phase is low-risk because no production applications are affected yet.
Phase two migrates the first pilot application — typically an internal tool with low risk. The pipeline is refactored so that instead of a kubectl step it generates a config repo PR. Application developers experience the GitOps workflow for the first time here and provide valuable feedback. Phase three rolls the pattern out to further applications; phase four covers business-critical production workloads.
A common mistake during migration is attempting to run both models (push and pull) in parallel — this almost always ends in drift conflicts, because both the old pipeline and the new controller want to modify the cluster state. A cleaner approach is a hard cutover per application on a defined date: from day X, all changes flow through GitOps and the old pipeline is decommissioned.
Reepa's Setup for Mid-Market Clients
For our mid-market clients we typically use ArgoCD as a hub-and-spoke solution with a dedicated ArgoCD cluster and one to three workload clusters (dev/staging shared, prod separate, optionally a DR cluster). The repo structure separates application and config repos, with the config repo being a monorepo with an app-of-apps bootstrap. Secrets are managed via SealedSecrets in the initial phase, with a strategic migration path to the External Secrets Operator with HashiCorp Vault once a second production environment is added.
For applications with high business risk we add Argo Rollouts with Prometheus-based analysis runs. In heavily regulated industries (healthcare, finance), the audit pipeline is extended with signed commits (sigstore/gitsign) and policy-as-code (OPA Gatekeeper or Kyverno as admission controllers). The audit read permission on the config repo simultaneously satisfies requirements from GDPR Article 32, ISO 27001 Control A.8.32, and NIS2 regarding traceable change processes.
The typical project scope for an initial setup with two clusters and around ten applications is 20 to 30 consulting days; ongoing support is usually most valuable as a retainer of two to four days per month. Organizations that take the full setup as a managed service avoid the initial ramp-up curve but cede some control — the right choice depends on the client's platform maturity.
Frequently Asked Questions
ArgoCD or Flux — which is the better fit for mid-market companies?
For mid-market businesses with a small platform team, ArgoCD is the more common recommendation because its built-in web UI significantly simplifies onboarding for application teams and makes sync status, drift, and rollbacks visible without the command line. Flux is the better choice if you have a pure CLI- and GitOps-oriented platform culture, deploy many clusters with identical configurations, and see the CNCF component model (Source Controller, Kustomize Controller, Helm Controller) as an architectural advantage. Both are production-grade and CNCF-graduated.
Do we need GitOps if we only operate a single cluster?
Yes, GitOps pays off even with a single cluster. The core value lies not in multi-cluster scaling but in auditability (every change is a Git commit with author and rationale), reproducibility (the cluster state can be reconstructed from the repo at any time), and rollback speed (a git revert plus automatic sync restores the previous state within minutes). All three properties deliver immediate returns in a single-cluster setup, especially in a compliance context.
How do we handle secrets — they don't belong in Git, do they?
Plaintext secrets certainly don't belong in Git, but encrypted secrets absolutely do. The three established patterns are SealedSecrets (Bitnami controller that encrypts with a cluster-specific public key), Mozilla SOPS (encryption with age or KMS, readable via Flux SOPS integration or an ArgoCD plugin), and the External Secrets Operator (Git contains only references; the actual secrets live in Vault, AWS Secrets Manager, or Azure Key Vault). For mid-market setups, SealedSecrets is the easiest entry point; External Secrets with Vault is the strategically strongest long-term solution.
What does a sensible repo structure look like — one repo or several?
For mid-market setups we recommend splitting between the application repo (source code and Helm chart of the application) and the config repo (the manifests observed by ArgoCD or Flux). Within the config repo, the app-of-apps pattern in ArgoCD or a Kustomization hierarchy in Flux provides a clean separation between platform services (Ingress, Monitoring, Cert-Manager), shared services, and application teams. Each environment (dev, staging, prod) gets its own folder with Kustomize overlays, not its own branch — using branches as environment separators creates hard-to-control drift.
What does GitOps adoption realistically cost for a mid-market company?
Both ArgoCD and Flux are open source and free; the cost lies in setup and migration. For a mid-market operation with two to four Kubernetes clusters and 10 to 30 applications, we estimate 15 to 30 consulting and implementation days, which typically translates to a project budget between €25,000 and €60,000. On top of that come internal efforts for application teams (cleaning up Helm charts, migrating secrets, adapting pipelines) in the range of 5 to 15 person-days per team. Ongoing operations require roughly 5 to 15 percent of one platform team position.
Ready to Adopt GitOps in a Structured Way?
Let's talk for 30 minutes with no commitment. We assess your current CD maturity, recommend ArgoCD or Flux with reasoning, propose a suitable repo structure, and deliver a realistic migration roadmap for the first 90 days — including a secrets strategy and rollout sequence.
Schedule a 30-Minute Call