ArgoCD in Practice: 7 Tips for More Stable GitOps

This article was last updated on: June 29, 2026 pm

Introduction

I’ve been recently building a multi-tenant Kubernetes platform with ArgoCD handling the GitOps implementation. To be honest, I always thought I knew this tool pretty well, but once I hit production-grade multi-team, multi-cluster scenarios, all kinds of pitfalls started popping up.

I’ve been watching a lot of GitOps/ArgoCD tech talks on YouTube lately, and also came across Red Hat/ArgoCD’s official blog posts on recommended GitOps practices. I couldn’t resist putting pen to paper — combining those insights with my own recent experience, I’ve distilled several key takeaways that I hope will help anyone currently adopting or about to adopt GitOps.

Seven Steps: Making ArgoCD More Stable, Isolated, and Controllable

Previous articles covered ArgoCD basics, but in production, knowing how to configure isn’t enough — you need to configure it well. This time we skip the concepts and go straight to practical tips on making the “GitOps engine” run more reliably.

Step 1: Don’t Let It Starve or Go Rogue — Set Resource Limits Properly

ArgoCD itself runs as Pods that consume cluster CPU and memory. Without resource limits, it can eat up all resources on a node, impacting other workloads. Especially in large-scale or multi-cluster setups, the application-controller and repo-server can be quite resource-hungry (my application-controller runs at 16GB memory per pod). Resource requests and limits are a must.

Here’s my approach:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# argocd-cm.yaml or Operator spec
server:
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "1Gi"

controller:
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "1"
memory: "2Gi"

repoServer:
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "1Gi"

These values should be tuned based on your cluster size and number of applications, but remember one principle: set requests generously, and limits sufficiently.

Step 2: Don’t Fight Raw YAML — Pick Helm or Kustomize

ArgoCD doesn’t force you to use Helm or Kustomize, but I strongly recommend against managing raw YAML directly.

  • Drawbacks of maintaining raw YAML:

    • Too much duplicated code, especially for multi-environment setups (dev/staging/prod).
    • Error-prone — miss one environment, and you’re blind during DR.
    • Difficult to update and maintain, with complex version management.
  • Recommended strategy:

    • Prefer Helm: If you’re doing standard application releases with a Chart repository and your team is familiar with Helm, go with Helm. ArgoCD’s Helm support is native and can automatically render Charts.
    • Alternative — Kustomize: If you prefer the Kubernetes-native approach, or your project structure is complex (e.g., heavy use of overlays), Kustomize is also a solid choice.

I personally lean toward Helm because of its stronger templating capabilities and richer ecosystem (e.g., tons of ready-made Charts on ArtifactHub). But if you’re managing platform-level configuration (CRDs, Operators), Kustomize might be a better fit.

Step 3: Separate Source Code from Manifests — Clear Ownership, Security First

This is an easily overlooked point. Many people put application code and ArgoCD Application manifests in the same Git repo.

What’s wrong with that?

  • Different lifecycles: Application code changes daily, but ArgoCD manifests might change once every few weeks. Mixing them makes version management chaotic.
  • Unclear permissions: Developers have write access to the code repo, but they shouldn’t have permission to modify Application resources (which could let them bypass approval and deploy directly).
  • Security risk: If a developer’s repo gets compromised, attackers could modify ArgoCD configuration, such as pointing to a malicious image registry.

Best practice:

  • Source Repo: The application’s own code repository (Java, Go projects, etc.), maintained by the development team.
  • Manifest Repo: Stores ArgoCD Application, AppProject, and Helm Chart or Kustomize overlay files. Maintained by the platform/SRE team with strict write access control.

Step 4: Maximum Isolation — Separate Application and Platform Instances

This is a practice recommended by Red Hat, and I consider it the core principle for multi-tenant scenarios.

Imagine: a team’s Application resource gets accidentally deleted, causing the entire ArgoCD application-controller to re-sync — a process that could impact deployments for all other teams.

Solution: Create separate ArgoCD instances for different teams. (Of course, you could also share a single ArgoCD instance with strict RBAC controls depending on your situation.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Namespace
metadata:
name: team-a-gitops
---
apiVersion: argoproj.io/v1alpha1
kind: ArgoCD
metadata:
name: team-a
namespace: team-a-gitops
spec:
# Configure independent repo server, controller, dex server, etc. for team-a
server:
route:
enabled: true
hostname: argocd-team-a.example.com
repo:
# Restrict which repos team-a can access
...

The above is an OpenShift example using the ArgoCD Operator. Typically, to create multiple instances, you can simply deploy multiple instances using the Helm chart.

Note: This might sound heavy, but it’s absolutely worth it in enterprise scenarios. Each instance is autonomous — one team’s mistakes won’t affect the cluster configuration or other teams’ applications.

Step 5: Beware the Hidden Traps of Declarative Configuration

ArgoCD relies on declarative configuration (Application, AppProject CRDs) for management. But here’s the catch: desired state ≠ actual state.

For example, you configure an Application expecting it to create three Deployments. If you remove a Deployment YAML block from the Git repo, ArgoCD will delete it. But if someone manually runs kubectl edit on a field in the cluster, ArgoCD will revert it to the Git state.

So where’s the problem?

  • Configuration drift has multiple sources: Beyond the Git repo, ArgoCD’s own Web UI and CLI can modify things directly. If someone (say, me, with a fat-finger moment) changes syncPolicy via the UI and forgets to commit to Git, the desired state and Git are now out of sync.
  • The Application itself can drift: Imagine modifying an Application parameter via the Web UI (e.g., changing targetRevision to a different branch) — this change won’t automatically sync back to Git.

My recommendations:

  • All-in Git: All ArgoCD configuration changes must originate from the Git repo. The Web UI is for viewing status and manually triggering syncs only.
  • Use argocd app diff to verify: Add a step in your CI/CD pipeline to run argocd app diff against the Git repo, ensuring no unexpected configuration drift.
  • Monitor ArgoCD itself: Use Prometheus to monitor ArgoCD metrics like argocd_app_info. If any Application enters OutOfSync state, trigger an alert. Alternatively, use ArgoCD’s notifications-controller to send alert notifications.

Step 6: For Multi-Team Collaboration, AppProject Is Your Best Friend

Permission management is mandatory in multi-team scenarios. AppProject is built exactly for this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-b-project
namespace: argocd
spec:
sourceRepos:
- 'https://gitlab.example.com/team-b/*' # Can only pull from team-b's repos
destinations:
- namespace: 'team-b-*' # Can only deploy to team-b related namespaces
server: 'https://kubernetes.default.svc'
clusterResourceWhitelist:
- group: '*'
kind: '*'
namespaceResourceWhitelist:
- group: '*'
kind: '*'

AppProject provides strict control over:

  • Who (sourceRepos) can pull what code?
  • Where (destinations) can they deploy?
  • What resources can they create (clusterResourceWhitelist / namespaceResourceWhitelist)?

Honestly, this is the cornerstone of multi-tenant GitOps — without it, all downstream isolation is just talk.

Step 7: Don’t Blindly Follow “Best Practices”

One last thing I want to call out. There are plenty of ready-made “ArgoCD best practices” templates online, but you can’t just copy-paste them.

Red Hat’s experts also say: adapt based on your organization’s structure and YAML management tools.

  • If your team structure is flat and projects are simple, a single ArgoCD instance + Helm/Kustomize is sufficient.
  • If you’re a platform team serving multiple business units, you need multiple instances + AppProject + strict access control.
  • If you’re still using raw YAML, don’t rush into Kustomize — evaluate the migration cost first.

Disclaimer: All practices recommended in this article come from my own production experience and Red Hat’s official recommendations. Don’t copy blindly — understand the reasoning behind them.

Summary

ArgoCD is a powerful tool, but using it well requires more than knowing how to configure it — it demands a deep understanding of GitOps design principles.

  • Resource limits: Prevent one machine from being consumed.
  • Tool selection: Helm or Kustomize — don’t hand-write YAML.
  • Repo separation: Keep source code and manifests apart.
  • Instance isolation: Separate application and platform instances.
  • Beware pitfalls: All-in Git — don’t modify via the UI.
  • AppProject: Permission guardrails for multi-tenancy.
  • Adapt to your needs: Don’t blindly apply templates.

│ Unity of knowledge and action. Knowing how to configure is only the first step — getting hands-on, hitting the pitfalls, and doing retrospectives is how you truly turn GitOps into your team’s infrastructure.

References


ArgoCD in Practice: 7 Tips for More Stable GitOps
https://e-whisper.com/posts/9039/
Author
east4ming
Posted on
June 9, 2026
Licensed under