Why GitOps Deployments Actually Change Team Velocity (It's Not the Automation) | PulseSoft
PulseSoft

Why GitOps Deployments Actually Change Team Velocity (It's Not the Automation)

PulseSoft Team · October 1, 2026 · 8 min read

Introduction

The pitch for GitOps usually focuses on the wrong benefit. People talk about it like it's a faster CI/CD pipeline, when the actual velocity gain has almost nothing to do with speed and everything to do with removing the coordination tax that imperative deployment processes force on every team sharing a cluster. I've run migrations where deploy time barely changed after adopting GitOps deployments, and the team still shipped noticeably faster within a quarter, because the bottleneck was never pipeline execution time, it was who had to talk to whom before a change could go out.

That distinction matters because most teams evaluate GitOps against the wrong metric and conclude it's not worth the migration effort. If you're only measuring "how fast does kubectl apply finish," you're going to miss the actual thing that changes.

This post is about what GitOps deployments actually fix, what they don't, and the specific AWS and Kubernetes architecture decisions that determine whether a GitOps migration delivers the velocity gain teams expect or just adds a new layer of tooling on top of the same coordination problems.

The Core Problem: Imperative Deployment Is a Coordination Problem Disguised as a Tooling Problem

In an imperative deployment model (someone running kubectl apply, helm upgrade, or a CI job that does the same thing directly against the cluster), the cluster's actual state and the state your team believes it's in can silently drift apart. Someone makes a manual kubectl edit during an incident and never reconciles it back into the source-controlled manifest. A CI job partially fails halfway through a multi-resource deploy. Two engineers deploy to the same namespace within minutes of each other and the second deploy's context doesn't account for what the first one just changed. None of this is visible until something breaks and someone has to reconstruct what state the cluster is actually in versus what the manifests say it should be.

GitOps deployments (using a tool like ArgoCD or Flux to continuously reconcile cluster state against a Git repository, rather than pushing changes to the cluster directly), solves this by making Git the single source of truth and making the reconciliation loop, not a human running a CLI command, the only path by which cluster state changes. If someone manually edits a resource during an incident, the GitOps controller detects the drift and reverts it back to match Git on the next reconciliation cycle, which is either exactly the safety net you want or a genuinely disruptive surprise depending on whether the person doing the manual edit knew that was going to happen.

The velocity gain shows up specifically in multi-team environments. Without GitOps, every deploy to a shared cluster typically requires some combination of: checking who else might be deploying to the same namespace right now, verifying CI/CD pipeline credentials still have cluster access (a surprisingly common source of Friday-afternoon incidents when IAM roles or kubeconfig tokens expire), and manually confirming the deploy succeeded because there's no single place that shows desired-state-versus-actual-state clearly. GitOps collapses all of that into a single, observable reconciliation status per application, which means teams stop needing to coordinate around a shared, error-prone deployment mechanism and start operating independently against a system that enforces consistency on its own.

The most common way teams get this wrong: they adopt ArgoCD or Flux but keep pushing changes to the cluster directly for "quick fixes," treating GitOps as the happy-path process and imperative access as the escape hatch. That escape hatch is exactly where the coordination problems GitOps was supposed to solve creep back in, and it usually happens during incidents: the highest-stakes moment for state to be predictable, and the moment teams are most tempted to bypass the process.

AWS Deep Dive: Making GitOps Actually Work on EKS

ArgoCD vs Flux: The Decision That Actually Matters Is Application Structure, Not Feature Comparison

Most ArgoCD-vs-Flux comparisons focus on UI quality (ArgoCD has a genuinely useful web UI for visualizing sync status and diffs; Flux is UI-optional and more commonly paired with a separate dashboard or the CLI) or ecosystem maturity. The decision that actually determines your team's experience is how well each tool maps onto your application structure. ArgoCD's Application and ApplicationSet resources work well when you have a moderate number of well-defined services and want strong per-application visibility into sync status. Flux's Kustomization-based approach with multi-tenancy support through separate GitRepository sources tends to scale more cleanly when you have many teams each owning their own repo and needing strict isolation from each other's reconciliation.

Rendering diagram…
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: checkout-service
  namespace: argocd
spec:
  project: commerce
  source:
    repoURL: https://github.com/pulsesoft/checkout-service.git
    targetRevision: main
    path: k8s/production
  destination:
    server: https://kubernetes.default.svc
    namespace: checkout
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=false

The selfHeal: true setting is the specific line that determines whether GitOps is actually enforced or just a suggestion. Without it, ArgoCD will show drift when someone manually edits a resource but won't automatically correct it, which some teams genuinely want during an initial rollout to build trust in the system before turning on full enforcement, but which means you haven't actually closed the coordination gap yet if it stays off indefinitely.

IAM and Access Boundaries: Who Can Push to Git Now Matters More Than Who Has kubectl Access

GitOps deployments shift the access control problem from "who has kubectl credentials against the cluster" to "who can merge to the branch the GitOps controller reconciles from." This is a genuine security improvement, Git provides audit history, required reviews, and branch protection natively, which is a much stronger control surface than cluster RBAC alone. But it only works if you actually lock down direct cluster access to match. Teams that adopt ArgoCD but leave broad kubectl access in place for "just in case" have built a strong front door with an unlocked back door.

On EKS specifically, this means scoping the ArgoCD or Flux controller's own IAM permissions tightly via IRSA or Pod Identity (the controller needs access to reconcile the resources it's responsible for, not cluster-admin), and separately auditing who has direct EKS API access through aws eks update-kubeconfig and cluster RBAC bindings, since that access bypasses the entire GitOps audit trail.

aws eks associate-access-policy \
  --cluster-name production \
  --principal-arn arn:aws:iam::123456789012:role/argocd-controller-role \
  --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSEditPolicy \
  --access-scope type=namespace,namespaces=checkout,payments

The non-obvious gotcha: EKS Access Entries (the newer, IAM-native approach to cluster access control, replacing the older aws-auth ConfigMap pattern) and legacy aws-auth ConfigMap-based access can coexist on the same cluster during migration, but they don't automatically reconcile with each other, meaning a permission granted through one mechanism won't show up when you audit the other. If your cluster predates EKS Access Entries, verify which mechanism is actually governing access before assuming your RBAC audit is complete, I've seen clusters where a stale aws-auth entry granted broad access that nobody remembered existed, invisible to anyone auditing only Access Entries.

Secrets in a GitOps World: You Cannot Commit Plaintext, But You Also Can't Skip the Reconciliation Model

The obvious GitOps problem is secrets: you can't commit plaintext credentials to a Git repository that's the source of truth for your cluster state, but the entire GitOps model depends on Git describing everything the cluster needs. The practical solution is encrypting secrets at rest in Git using something like Sealed Secrets or SOPS with AWS KMS as the encryption backend, so the encrypted value is safe to commit and only decryptable by a controller running inside the cluster with the right KMS permissions.

sops --encrypt --kms arn:aws:kms:us-east-1:123456789012:key/abc-123 \
  --encrypted-regex '^(data|stringData)#x27; \
  secrets/checkout-db-credentials.yaml > secrets/checkout-db-credentials.enc.yaml

Alternatively, the External Secrets Operator pattern (where Git contains only a reference to a Secrets Manager path, and the actual secret value is fetched at reconciliation time and never stored in Git at all, even encrypted), avoids the KMS-decryption-in-cluster complexity entirely and keeps secret rotation fully decoupled from your GitOps deploy cycle. Most teams running mature GitOps setups on AWS land on the External Secrets Operator pattern specifically because it means rotating a database credential in Secrets Manager doesn't require a Git commit at all.

Enjoying this so far?

Join thousands of engineers receiving practical engineering, Cloud, Distributed Systems, Infrastructure and AI engineering insights.

No spam. Unsubscribe anytime.

Tradeoffs & Decision Framework

Full automation (selfHeal) vs staged rollout: Turning on full automated drift correction from day one enforces the GitOps model immediately but can be genuinely disruptive if your team still has habits of manual kubectl intervention during incidents. Staging the rollout (sync visibility first, auto-heal later), builds trust but delays the actual coordination benefit you're migrating for. The right call depends on how disciplined your on-call process already is; teams with strong incident discipline can go straight to full automation, teams still relying on manual cluster surgery during incidents need the staged approach first.

Repo structure, monorepo vs repo-per-service: A monorepo for all Kubernetes manifests gives platform teams a single place to enforce standards and review changes, but creates a shared bottleneck for approvals across unrelated teams and a larger blast radius for a bad merge. Repo-per-service gives teams full autonomy over their own deploy cadence but multiplies the number of repos the platform team needs to apply consistent policy to. Most orgs past a handful of teams land on repo-per-service with policy enforced through shared CI templates or admission control rather than through a single repo's review process.

What breaks at small team size vs what breaks at scale: At small team size, the coordination problem GitOps solves often doesn't exist yet: one or two engineers deploying to a shared cluster rarely step on each other, and the GitOps tooling overhead can outweigh the benefit. At scale, with multiple independent teams deploying to shared infrastructure, the coordination tax of imperative deployment becomes the dominant source of deploy-related friction, and GitOps's velocity gain becomes real and measurable rather than theoretical.

Lessons From the Field

  1. After migrating a 25-engineer org from Jenkins-triggered kubectl apply to ArgoCD, the deploy frequency metric barely moved in the first month: the real change was a 70% drop in Slack messages asking "is anyone else deploying to staging right now."

  2. In an engagement where we left selfHeal off for the first six weeks post-migration, we caught two separate incidents where an engineer had made a manual fix during an outage and forgotten to backport it to Git, exactly the drift GitOps is designed to surface.

  3. I've seen teams treat ArgoCD adoption as complete while leaving broad IAM-based kubectl access untouched for the entire engineering org: the audit trail GitOps is supposed to provide is worthless if there's an unaudited parallel path to the same cluster.

  4. The GitOps migration that went smoothest was the one where we moved secrets to the External Secrets Operator pattern before adopting ArgoCD, not after, retrofitting secrets management onto an already-live GitOps pipeline is a much messier sequencing than doing it first.

  5. Every stalled GitOps rollout I've inherited had the same root cause: the team adopted the tooling but kept an unofficial imperative escape hatch for "urgent" changes, which meant the coordination problem GitOps was meant to solve never actually went away, it just got a smaller surface area.

Final Thoughts

GitOps deployments are going to keep becoming the default expectation for any team running Kubernetes at more than a handful of engineers, not because the tooling is getting more impressive, but because the coordination cost of imperative deployment scales badly and teams are increasingly running into it earlier in their growth than they used to. The teams who get the real velocity gain are the ones who treat GitOps as an access control and coordination model first, and a deployment automation tool second.

This is the kind of deployment architecture we help teams design at PulseSoft, if your team is evaluating a GitOps migration and wants to get the access model right the first time, let's talk.

Key Takeaways

  • The real velocity gain from GitOps deployments comes from removing deploy coordination overhead between teams sharing a cluster, not from making individual deploys execute faster.
  • GitOps only closes the coordination gap if direct imperative cluster access is actually locked down to match, leaving a kubectl escape hatch open undermines the entire model.
  • ArgoCD's selfHeal: true setting is the specific configuration that determines whether GitOps is enforced or just observed, without it, drift is visible but not corrected.
  • Choose ArgoCD for strong per-application sync visibility with a moderate service count, and Flux for scaling multi-tenant GitOps across many independently-owned repos.
  • Use the External Secrets Operator pattern instead of encrypting secrets in Git wherever possible: it decouples secret rotation from your deploy cycle entirely.
  • EKS Access Entries and legacy aws-auth ConfigMap access can coexist without reconciling, so audit both before assuming your cluster's access control picture is complete.
  • GitOps delivers the least value at small team size with low deploy coordination overhead, and the most value once multiple independent teams are deploying to shared infrastructure.

Get insights like this in your inbox

Join thousands of engineers receiving practical engineering, Cloud, Distributed Systems, Infrastructure and AI engineering insights.

No spam. Unsubscribe anytime.

← Back to Blog