In the early days of building AravaliStack, we made a decision that seemed radical to some of our early users: every piece of platform state — infrastructure, application deployments, cost budgets, ML training jobs, network policy — must be declared in Git. No exceptions. No kubectl exec in production. No clicking through a dashboard to change a replica count. Git is the only control plane.
Eighteen months and several hundred production deployments later, we haven't regretted it once.
The problem GitOps solves
Before GitOps, the typical enterprise Kubernetes workflow looks like this: developers write YAML, apply it to a cluster with kubectl, tweak things when they break, sometimes write down what they did, often don't. The cluster accumulates state that nobody fully understands. "Works on my machine" becomes "works on our cluster" — until it doesn't, and nobody can reproduce the state that was working.
For regulated industries, this is worse than an inconvenience. When an RBI auditor asks "show me the configuration of your payment processing service as it was on 14 February 2026," the answer in a traditional workflow is: "we'll check the cluster, but we might have made some changes since then." That is not an acceptable answer.
What GitOps actually means in practice
GitOps means two things: declarative state, and automated reconciliation.
Declarative state means every resource in your platform — Kubernetes deployments, HPA configurations, network policies, Vault secret paths, cost budget limits, ML training job specs — is defined as a file in a Git repository. When you want to change something, you change the file and commit. The Git history is the complete history of your infrastructure.
Automated reconciliation means a controller (Flux CD or ArgoCD) continuously compares the desired state in Git against the actual state in the cluster. Any drift — whether caused by a failed deployment, a manual kubectl change, or a node failure — is detected and automatically corrected. The cluster always converges back to what Git says it should be.
The three things GitOps gives you that dashboards don't
1. A complete, immutable audit trail
Every change to every piece of platform state has a Git commit hash, an author, a timestamp, a commit message, and (if you use pull requests) a review trail. When a regulator asks what your production configuration looked like on a specific date, you git checkout that commit and show them. No reconstruction. No "we think it was..."
2. Automatic disaster recovery
When you lose a cluster — hardware failure, accidental deletion, catastrophic upgrade — recovery is deterministic. You point Flux at the Git repository and it rebuilds the entire cluster to the last committed state. We have run this drill multiple times. In a well-structured GitOps setup, full cluster recovery from scratch takes under 45 minutes.
3. Pull requests as the change management process
In most enterprises, change management is a separate process — JIRA tickets, CAB approvals, email chains. In a GitOps workflow, the pull request IS the change management process. The description explains why, the diff shows exactly what changes, the review trail shows who approved, and the merge commit records when it went to production. No separate tool required.
Where we extended it beyond the obvious
Most teams use GitOps for application deployments. We extended it further:
- Cost budgets. Team budget limits are declared in Git. When a team wants a higher budget, they open a PR. Finance reviews it. It's approved or denied with a comment. The audit trail is automatic.
- OPA policies. Every security policy is a Rego file in Git. Policy changes go through code review with the same process as application changes. Security policy has never been accidentally changed without review.
- ML training jobs. Experiment configurations, training schedules, and GPU allocations are declared as CRDs in Git. Reproducibility is not a feature request — it is a consequence of the architecture.
- Network policies. Kubernetes NetworkPolicy manifests define which services can talk to which. Any service that isn't explicitly permitted to communicate cannot. This is zero trust at the network layer, enforced through GitOps.
The one objection we hear most
"What about hotfixes? Sometimes you need to change something in production right now."
Our answer: yes, and you still use Git. The process is faster — you skip the full review cycle, you get one senior engineer to approve, you merge — but you still use Git. The reason is not bureaucracy. The reason is that a hotfix applied directly to the cluster will be undone by Flux the next time it reconciles, which creates exactly the category of incident you were trying to avoid. Git is not slow. Unreviewed PRs can merge in under 5 minutes when urgency requires it.
We chose GitOps as the only control plane not because we wanted to add process, but because we wanted to eliminate the class of incidents that comes from undocumented, unreviewable, unrepeatable changes to production state. Eighteen months in, that class of incident has not occurred once.
