Escaping YAML Hell: Scaling GitOps & ArgoCD for 50+ Microservices
How we eliminated configuration drift, automated deployments, and scaled ArgoCD across multi-region EKS clusters for a Series-B SaaS platform.

The Problem: Death by a Thousand YAML Files
GitOps promises an operational utopia: your Git repository is the single source of truth for your infrastructure. But for a rapidly growing Series-B SaaS client, that dream quickly turned into a nightmare of configuration drift and "YAML fatigue."
When they had 5 microservices, managing Kubernetes manifests manually was fine. By the time they hit 50 microservices across 4 environments (Dev, Staging, EU-Prod, US-Prod), they were maintaining over 1,500 YAML files.
The Breaking Point
Deployments were taking 45+ minutes. Developers were afraid to merge infrastructure PRs. Staging environments were constantly drifting from Production because developers would manually kubectl apply hotfixes and forget to update Git.
The Fix: Restructuring for "App of Apps"
We realized the issue wasn't ArgoCD—it was how they were using it. They had a single flat repository containing hundreds of Kustomize overlays. We executed a complete restructure using the App of Apps pattern and ApplicationSets.
1. Abstracting Complexity with Helm
First, we stopped developers from writing raw Kubernetes manifests. We created a single, standardized, internal Helm chart called saas-microservice-base. Instead of 10 different YAML files for Deployments, Services, Ingress, and HPA, developers only needed to write a 15-line values.yaml file.
2. Dynamic Deployments with ApplicationSets
Rather than manually registering 50 apps in ArgoCD, we implemented ArgoCD ApplicationSets. Using the Git generator, ArgoCD automatically discovers new microservices based on repository directory structures.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: cluster-workloads
spec:
generators:
- git:
repoURL: https://github.com/org/gitops-repo.git
revision: HEAD
directories:
- path: apps/*/overlays/production
template:
metadata:
name: '{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/org/gitops-repo.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true3. Closing the Loop with Argo Image Updater
The final piece of the puzzle was deployment automation. We configured Argo Image Updater to watch the client's ECR registry. When a new Docker image passes CI tests and is pushed to ECR, the Image Updater automatically detects the semantic version tag, writes the new image tag back to the Git repository, and triggers ArgoCD to sync.
Before Velocity Stream
- 45-minute manual deployment process
- Constant drift between staging and prod
- 1,500+ raw YAML files to maintain
- Developers required K8s expertise
After Implementation
- 3-minute automated deployments
- Zero configuration drift (Self-healing active)
- Standardized Helm abstraction
- "Invisible" infrastructure for developers
The ROI of Platform Engineering
By shifting from a raw DevOps model to a true Platform Engineering approach, we didn't just fix a deployment pipeline; we recovered hundreds of engineering hours per month. Developers went back to writing features instead of fighting YAML formatting errors.
If your GitOps setup feels like it's slowing you down rather than speeding you up, it might be time to rethink your repository architecture.

