ArgoCD and GitOps: Declarative CD for Kubernetes

What GitOps Means

GitOps has a precise definition. Cluster state is described declaratively in a git repository. A controller running in the cluster reconciles the actual state to match the desired state in git. Changes happen by committing to git, never by running kubectl apply. The ArgoCD documentation is the primary reference for the most widely adopted implementation.

The benefits: auditable history (git log), clear rollback (git revert), and a separation of who can change what (git permissions). The cost: another component to operate, a learning curve, and friction when something needs to be changed urgently and going through git review is too slow.

ArgoCD’s Model

ArgoCD watches one or more git repositories. Each Application resource points to a path in a repo and a target namespace in a cluster. ArgoCD pulls the manifests, compares them to the live state, and (depending on sync policy) either applies the diff automatically or shows it for manual approval.

The UI is the headline feature. Visualizing application state, diffs, sync history, and resource trees is dramatically easier than kubectl describe loops.

Repository Structure

The dominant patterns are ‘config repo per environment’ (one repo for dev, one for staging, one for prod) or ‘monorepo with environment overlays’ (one repo, paths per environment, often using Kustomize or Helm).

Monorepo is simpler for small teams. Per-environment repos make access controls clearer at scale — you can grant production write access to a smaller group.

App-of-Apps and ApplicationSets

For more than a handful of applications, managing each one as a separate ArgoCD Application gets tedious. The app-of-apps pattern uses a single Application that creates other Applications.

ApplicationSets are the more modern answer. A single ApplicationSet declares a template and a generator (git directories, list of clusters, pull requests), and ArgoCD materializes one Application per match. The pattern scales much better than app-of-apps. See the ApplicationSet documentation for generator types and use cases.

Where GitOps Doesn’t Fit

GitOps works well for declarative infrastructure: cluster configuration, application deployments, policy. It works less well for genuinely imperative actions: database migrations, one-off jobs, emergency rollbacks under time pressure.

For those cases, escape hatches matter. Most teams running GitOps still allow direct kubectl access for emergencies, with the discipline that changes must be reflected back in git afterward.

Multi-Cluster Patterns

ArgoCD can manage applications across many clusters from a central instance. Each cluster is added as a target with credentials; applications specify their target cluster.

For larger deployments, the App-of-Apps pattern combined with ApplicationSets generates per-cluster applications from a single template. Cluster lifecycle (creation, upgrade, decommission) is then a matter of updating the ApplicationSet generator inputs.

Secrets in GitOps

Plain-text secrets can’t live in git. Sealed Secrets encrypts secrets with a controller-held key; the encrypted SealedSecret CRD lives in git, the controller decrypts at apply time.

External Secrets Operator (ESO) is the more flexible alternative. ESO fetches secrets from Vault, AWS Secrets Manager, GCP Secret Manager, or similar at deploy time. The git repo contains only references; the secrets themselves stay in the secret manager. ESO is the dominant choice in 2026.

Sync Strategies and Auto-Sync

ArgoCD applications have sync policies: manual (an admin clicks ‘sync’ to apply changes), automatic (every detected drift gets applied), automatic with prune (also delete resources removed from git), automatic with self-heal (overwrite any manual changes).

The conservative default is manual or automatic without prune/self-heal. Once teams are comfortable, enable automatic with self-heal — it makes the cluster state match git exactly, which is the GitOps promise.

Some applications need to stay manual: those where applies have side effects (data migrations) or where coordination with external systems matters. Mix and match based on application characteristics.

Performance at Scale

ArgoCD can manage thousands of applications, but performance tuning becomes necessary above a few hundred. Application controller sharding (multiple controllers, each handling a subset of applications) distributes load.

Sync timing matters too. Default reconciliation interval (3 minutes) becomes expensive at scale. Webhook-triggered syncs from git events reduce polling load.

For very large deployments, ApplicationSets generate Applications from generators, which scales better than individually-managed Applications. Configure carefully — a misconfigured generator can create thousands of unintended applications.

Release Notes and Changelog Generation

Automated release notes from commit history close the loop between code changes and user-facing communication. Tools like release-drafter, semantic-release, and changesets generate changelogs from conventional commits or PR labels.

The discipline of writing PR titles and commit messages for downstream consumption pays back here. PR titles become changelog entries; clear titles make for clear changelogs.

For libraries with external users, automated semver bumping based on commit type (feat: minor, fix: patch, breaking change: major) reduces manual version management. The same tooling can publish to npm, PyPI, or other package registries on merge.

Security in CI/CD

CI/CD systems hold significant power: they can build code, sign images, push to registries, and deploy to production. Securing them matters.

Standard hardening: least-privilege credentials for each step, signed artifacts at each stage, audit logs of all pipeline executions, separation between build environments and production credentials.

Supply chain attacks via compromised CI are a real and growing threat. SLSA (Supply chain Levels for Software Artifacts) provides a framework for thinking about CI/CD security maturity. Most organizations land at SLSA level 1-2; reaching level 3 requires real investment but provides meaningful guarantees.

Pipeline Templating and Reuse

At scale, copy-pasted CI configuration becomes a maintenance burden. Every change to the standard pipeline requires touching dozens of repos.

Templating mechanisms vary by platform: GitHub Actions composite actions and reusable workflows, GitLab CI includes and templates, Jenkins shared libraries. Each provides a path to defining pipeline logic once and consuming it from many repositories.

The pattern that works: a small platform team maintains pipeline templates; service teams consume them by reference. Service-specific customization happens via variables and minimal local overrides. Template changes can be reviewed and tested centrally before propagating.

Build Cache and Performance

Build performance compounds at scale. A 30-second improvement on every pipeline run translates to hours per day across an organization.

Caching strategies matter most: dependency caches (npm, Maven, pip), Docker layer caches, intermediate build artifacts. Each cache type has different invalidation rules and storage requirements.

Remote caches shared across runners deliver the biggest improvement for monorepos and matrix builds. Bazel remote cache, Turborepo Remote Cache, and Nx Cloud all provide this for their respective ecosystems. Build times that dropped from 10 minutes to 1 minute aren’t unusual.

Putting It Into Practice

The patterns described throughout this article aren’t all equally important for every team. The right starting point depends on current state.

For teams without consistent CI/CD: focus first on basic pipeline reliability and speed. Inconsistent or slow pipelines undermine every other improvement you might try later.

For teams with working pipelines but high change failure rate: invest in better testing, smaller deployments, and explicit rollback procedures. The shift from ‘shipping is scary’ to ‘shipping is routine’ transforms how teams operate.

For teams with reliable CI/CD looking to advance: progressive delivery, deployment frequency improvement, and DORA metric tracking are the natural next steps. Each builds on the foundation rather than replacing it.

The advancement isn’t linear, and not every team needs every capability. Match the practices to the team’s actual constraints and let the rest wait.

Key Takeaways

The most important point throughout this guide: practical engineering decisions depend on specific context. Best-practice recommendations are starting points, not destinations. The right answer for your team depends on your scale, your existing tooling investment, your team’s experience, and the specific constraints you face.

Three principles worth carrying forward regardless of specific tool choices. First, measure what you change. Engineering improvements without measurement become folklore — claims without evidence. Track the metrics that show whether interventions are working.

Second, default to simpler architectures and tools. Complexity has cost. Each additional moving part is something to monitor, debug, upgrade, and eventually replace. Choose the simplest thing that meets your actual requirements, not the most sophisticated thing you could build.

Third, invest continuously in the boring foundations. Reliable CI, good observability, sensible access controls, and clear documentation pay back across every project. Skipping these for short-term feature velocity accumulates debt that eventually consumes the velocity it was supposed to enable.

The teams that operate well over the long term are usually not the teams with the most exotic tooling. They’re the teams with disciplined fundamentals, deliberate decision-making, and continuous incremental improvement.

Frequently Asked Questions

ArgoCD or Flux?

ArgoCD has the better UI and is more popular. Flux integrates more cleanly with some CI workflows. Both are competent.

Should I use one repo or many?

Monorepo for small teams (under 20 services). Per-environment repos when access control granularity matters.

How do I handle secrets in GitOps?

Don’t commit plaintext secrets. Sealed Secrets, External Secrets Operator, or SOPS-encrypted manifests are the common patterns.

What about app deployments triggered by CI?

The pattern is: CI builds an image, updates the image tag in the config repo, ArgoCD picks up the change. Argo Image Updater automates the tag-update step.