I have been running GitOps pipelines in production for a long time, and the one conversation I keep having is a variation of the same complaint: “We adopted Argo CD, we love it, but our promotion process is still a Bash script that someone wrote three years ago and nobody wants to touch.” The script checks if a tag exists in ECR, updates a Helm values file in the staging repository branch, opens a PR, and then hopes a human merges it before the release window closes. When something goes wrong, nobody is sure whether the script failed silently or the PR is just sitting in someone’s review queue.
This is the gap that GitOps with Argo CD and Flux was always supposed to solve but never fully did. Both tools are excellent at what they actually do: watching a Git repository and reconciling Kubernetes clusters to match the declared state. What neither tool was ever designed to do is decide when and how an artifact should cross an environment boundary. That gap is what Kargo fills.
Kargo reached v1.0 in October 2024 and is now in its second major generation at v1.10 and v1.11, built by the same team that created Argo CD at Akuity. In October 2026, Akuity announced Fleet Management for Kargo Enterprise, which extends the promotion model to hundreds of clusters. Based on Akuity’s 2026 Argo CD user survey, adoption of Kargo as a promotion mechanism rose from 2% to 20% of surveyed organizations in a single year. That trajectory is worth understanding.
The Problem GitOps Left Unsolved
Let me be precise about what the problem is, because “Argo CD doesn’t do promotion” sounds like a criticism of the tool. It is not. Argo CD is a deployment tool: you tell it what state a cluster should be in, and it enforces that state. It has no concept of “this thing came from staging and should go to production” because that is not a deployment concern. That is a release engineering concern.
In practice, teams fill this gap in one of three ways. The first is CI-driven promotion: a GitHub Actions or Jenkins job that edits Helm values, commits the change, and triggers Argo CD to sync. The second is Flux’s Image Automation, which watches a container registry and can automatically update image tags in Git. The third, and most common, is the three-year-old Bash script I mentioned above.
None of these solutions give you what a real promotion pipeline needs:
- An immutable, auditable record of exactly what was deployed to staging, and when
- A policy layer that says staging must be green for 30 minutes before a promotion to production is allowed
- A rollback that is precise: “revert production to Freight 42, not Freight 43”
- A way to gate promotions on external signals, like a test result, an approval, or a feature flag state
- A single source of truth for what version is running in each environment, across every team
When you try to build all of that with shell scripts and CI jobs, you end up with something fragile and hard to introspect. I have seen teams where promotion “state” was tracked in a spreadsheet because the CI jobs were so opaque that nobody could remember what was actually running in UAT.
Kargo’s core insight is that promotion is a first-class problem, not something to bolt onto your deployment tool. The project models it as a control plane for artifact movement, separate from but integrated with the deployment tool you already have.
Kargo Architecture: Warehouses, Freight, Stages, and Promotions
The four core concepts in Kargo are worth understanding precisely, because the naming is deliberate.
Warehouses are watchers. A Warehouse monitors one or more artifact sources: a container image registry, a Helm chart repository, or a Git repository. When new content appears, the Warehouse produces a new piece of Freight. You can think of a Warehouse as the entry point that converts external events (“a new image tag was pushed”) into internal Kargo events (“a new bundle of artifacts is available for promotion”).
Freight is an immutable snapshot of a versioned artifact bundle. A single piece of Freight might contain an image tag from ECR, a chart version from a private Helm repo, and a specific Git commit hash from an application repository. Crucially, Freight is content-addressed and immutable: Freight #1234 always refers to exactly the same combination of versions. This is what gives you a precise, auditable record. When you ask “what was running in production at 3pm last Tuesday?”, Kargo can answer because each deployment corresponds to a named, immutable Freight object, not a mutable image tag or a branch tip.
Stages represent your environment hierarchy: typically dev, staging, and production, though you can model whatever topology makes sense for your organization. Each Stage has a Kargo-managed deployment target, usually an Argo CD Application or a cluster resource, and a set of promotion policies. Stages are ordered: Freight flows through them in sequence, and each Stage can verify that the previous one was successful before accepting a new promotion.

Promotions are the act of moving a piece of Freight to a Stage. A Promotion runs a set of Promotion Steps, which are the actual operations: update a Helm values file, commit the change to Git, wait for Argo CD to confirm the sync succeeded, run a verification step. Each step is discrete and auditable. When a Promotion fails at step 3, you know exactly where it failed, and you can retry or roll back from that point.
The relationship between Freight and Stages is what separates Kargo from simpler automation. Argo CD knows that an Application is in sync. Kargo knows that Freight #1234 was deployed to dev at 10:14am, was verified healthy for 45 minutes, and then a human approved its promotion to staging, where it was successfully synced at 11:02am. Those are different levels of knowledge.
Installation and Basic Setup
Kargo runs as a set of Kubernetes controllers in your cluster. The installation is straightforward via Helm:
helm install kargo \
oci://ghcr.io/akuity/kargo-charts/kargo \
--namespace kargo \
--create-namespace \
--set api.adminAccount.passwordHash='$2a$...'
The CLI gives you a local UI and terminal access:
kargo login https://kargo.example.com
kargo get stages --project my-app
A minimal Kargo project for a single application looks like this:
apiVersion: kargo.akuity.io/v1alpha1
kind: Project
metadata:
name: my-app
---
apiVersion: kargo.akuity.io/v1alpha1
kind: Warehouse
metadata:
name: my-app
namespace: my-app
spec:
subscriptions:
- image:
repoURL: 012345678901.dkr.ecr.us-east-1.amazonaws.com/my-app
semverConstraint: ">=1.0.0"
---
apiVersion: kargo.akuity.io/v1alpha1
kind: Stage
metadata:
name: dev
namespace: my-app
spec:
requestedFreight:
- origin:
kind: Warehouse
name: my-app
sources:
direct: true
promotionTemplate:
spec:
steps:
- uses: git-clone
- uses: kustomize-set-image
with:
images:
- image: 012345678901.dkr.ecr.us-east-1.amazonaws.com/my-app
path: config/dev
- uses: kustomize-build
with:
path: config/dev
outPath: .kargo/rendered/dev
- uses: git-commit
- uses: git-push
- uses: argocd-update
with:
apps:
- name: my-app-dev
When a new image matching >=1.0.0 is pushed to ECR, the Warehouse produces new Freight and automatically promotes it to dev. From dev, promotion to staging requires either human approval or a verification policy.
Promotion Steps: The Building Blocks of Reliable Pipelines
The Promotion Steps model is what gives Kargo its flexibility. Each step in a Promotion is a discrete unit of work with a clear success or failure state. The built-in steps cover the most common patterns: git-clone, git-commit, git-push, helm-template, helm-update-chart, kustomize-set-image, kustomize-build, argocd-update, and argocd-wait.
The argocd-update step does more than trigger a sync: it can be configured to wait for Argo CD to confirm that the Application is healthy before the Promotion step succeeds. Pairing it with an argocd-wait step lets you block the pipeline until your liveness and readiness probes pass, your Helm hooks complete, and the Application reaches a stable state. That is a much stronger guarantee than “the CI job exited 0.”

For staging-to-production transitions, you will typically add a verification step. Kargo supports Argo Rollouts analysis templates as native verification, which integrates naturally if you are already using Argo Rollouts for canary deployments. An analysis run can query Prometheus, Datadog, or any HTTP endpoint to gate the production promotion on real signal rather than elapsed time alone.
Approval policies layer on top of verifications. You can require that staging be in a healthy state for a minimum duration and that a human with the right RBAC role approve the promotion before Kargo touches production. The approval is recorded with the approver’s identity and timestamp as part of the immutable Freight history.
Custom Steps: Containerized Logic in Your Promotion Pipeline
Kargo v1.10, released in April 2026, added Custom Steps. This addresses the long tail of promotion logic that built-in steps cannot cover. A Custom Step is a container image that runs as part of a Promotion and receives the current Freight state as input. The container can do anything: run an OPA policy check, invoke a Terraform plan, call an internal approval API, run a database migration dry run.
steps:
- uses: git-clone
- uses: kustomize-set-image
with:
images:
- image: 012345678901.dkr.ecr.us-east-1.amazonaws.com/my-app
path: config/staging
- uses: kustomize-build
with:
path: config/staging
outPath: .kargo/rendered/staging
- uses: git-commit
- uses: git-push
- uses: my-org/kargo-custom-steps/integration-test-gate:v1.2.0
with:
test_suite_url: https://tests.internal.example.com/api/run
wait_timeout: 600
- uses: argocd-update
with:
apps:
- name: my-app-staging
The integration test gate step in the example above is a container image your team writes and versioned in your own registry. It calls an internal test orchestration service, waits for results, and returns success or failure to Kargo. If it fails, the Promotion fails cleanly at that step, the Argo CD application is not touched, and the failure is logged against Freight #N with a timestamp and the error from the container.
Custom Steps also ship with HTTP notification support in v1.10. You can configure webhooks to fire at any step transition, sending Freight metadata to Slack, PagerDuty, or your internal event bus. I have seen teams use this to automatically comment on the JIRA ticket associated with the artifact version, so that product managers can see exactly when a specific change reached staging without asking someone to look up a deployment log.
Fleet Management: Promotion Across Hundreds of Clusters
The October 2026 announcement of Fleet Management for Kargo Enterprise extends the model from single-cluster deployments to fleet-scale rollouts. This is where the architecture starts looking genuinely different from anything you can build with Bash.
Fleet Management lets you define a Fleet, which is a group of clusters, and a rollout strategy: wave-based, percentage-based, or ordered by cluster metadata. A promotion to the fleet can specify that wave one should cover 10% of clusters, wait for a health threshold to pass, then continue to the remainder. If wave one fails to reach the health threshold, the rollout pauses and alerts the operator rather than continuing into the next wave.

This is directly relevant for the growing cohort of organizations running platform-as-a-service on top of Kubernetes, where a single change to a shared controller or admission webhook needs to roll out safely to hundreds of tenant clusters. Without tooling like this, those rollouts are either fully manual, which does not scale, or fully automated, which is a blast radius problem. See our coverage of multi-cluster management with Karmada and Fleet for the broader landscape of cluster fleet tooling.
Fleet Management is currently in private beta on the Akuity Platform, so this is not something you can drop into a self-hosted cluster today. But the direction is clear, and it matters for platform teams thinking about where environment promotion tooling is heading.
Kargo and the Broader GitOps Ecosystem
Kargo slots into the GitOps ecosystem without replacing the pieces that work well. It does not manage cluster state; Argo CD or Flux still does that. It does not build container images; your CI system still does that. It does not run integration tests; your test infrastructure still does that. Kargo is the control plane that coordinates these systems and models the movement of artifacts between environments as a first-class, auditable operation.
If you are using GitOps with Argo CD and Flux, Kargo extends the model upward into the release engineering layer. If you are using Argo Rollouts for canary deployments, Kargo integrates with it directly for verification. If you are running Helm charts as your packaging format, Kargo’s built-in steps support Helm values updates natively. The integrations are designed to compose with what you already have rather than requiring a rebuild.
One architectural consideration worth understanding: Kargo’s model is Git-centric. Promotions work by updating values files in Git repositories, which Argo CD then syncs. This means your GitOps repository structure needs to support this pattern. If you have a monorepo with environment-specific directories or separate per-environment branches, Kargo handles both. If your deployments are fully managed outside Git, such as a pure Helm install pipeline without a GitOps tool, Kargo is a harder fit.
The alternative to Kargo for teams already using Flux is the GitOps Promoter project, which takes a similar warehouse-and-promotion model but integrates more tightly with Flux’s Image Automation and pull-request-based workflows. It is less mature than Kargo as of this writing but is the natural comparison for Flux-native shops. The choice is mostly about which deployment tool you are standardizing on.
When to Adopt Kargo
I tell teams to consider Kargo when they hit at least two of these conditions:
You have more than two environments. A dev-to-production pipeline with no staging in between is simple enough that scripts work. Once you add staging, UAT, canary, and production, the promotion graph gets complex enough that a purpose-built tool pays for itself.
You have more than one team deploying to a shared cluster. Kargo’s Project model provides namespace-level isolation for promotion pipelines, so each team gets its own Warehouses, Stages, and policies without stepping on each other. Without this, promotion automation in a shared cluster turns into a coordination problem.
You need an audit trail for compliance. The immutable Freight history, combined with the per-step Promotion record, gives you a complete deployment audit trail essentially for free. If you are working toward SOC 2, HIPAA, or ISO 27001, this is the kind of tamper-evident record that auditors want to see. Compare this to the alternative, which is trying to reconstruct a deployment timeline from CI logs and Argo CD sync history.
Your current promotion process has broken at least once. This is the real signal. If you have had a silent promotion failure, an accidental duplicate rollout, or a case where nobody was sure what version was running in production, your current tooling is not up to the job. Kargo’s explicit state model eliminates most of these failure modes.
The teams I would not push toward Kargo right now are very small teams with a single service, a simple staging-to-production pipeline, and no compliance requirements. For those teams, the operational overhead of running Kargo controllers is not worth it compared to a well-maintained CI script with good error handling.
Getting Started in Practice
A few practical notes for teams evaluating Kargo.
Start with a non-critical service. The Kargo learning curve is mostly about understanding how Warehouses and Freight map onto your existing artifact flow. Working through that with a low-stakes service avoids the pressure of a production deployment while you figure out how to structure your Promotion Steps.
Integrate Kargo RBAC early. Kargo uses Kubernetes RBAC for access control, and the default configuration is fairly permissive. Define your project-level roles and cluster-level admin roles before you have ten teams using it, not after. See our guide to Kubernetes RBAC for the foundational patterns.
Think about Freight verification from day one. The argocd-wait-healthy step is the baseline, but teams that add metric-based verification early get much more value from the promotion gate. Even a simple Prometheus query checking error rate after a staging deploy catches regressions that a health check alone would miss.
Plan your Git repository structure. Kargo works best when each environment has a predictable location for image tags and chart versions, whether that is a values file path, a Kustomize overlay, or an environment-specific directory. If your repository structure is inconsistent across services, standardizing it is worth doing before rolling Kargo out broadly. The GitOps and Argo CD article has guidance on repository organization patterns that work well with Kargo.
The Promotion Problem Is Not Going Away
Twenty years of building infrastructure for software teams has convinced me that the most dangerous part of a deployment pipeline is always the human process that sits between environments. Not the CI system, not the deployment tool, but the handoff: the Slack message that says “I think the staging deploy is ready for prod,” the PR that sits unreviewed for two hours, the rollback that fails because nobody is sure whether the staging image tag is still the right one to revert to.
Kargo does not remove humans from the loop. Good release engineering still requires human judgment, especially for production gates. What Kargo does is give those humans accurate information and a reliable mechanism to act on it. When a Promotion to production requires approval, the approver sees the exact Freight being promoted, the verification results from staging, the diff between the current production Freight and the candidate, and the full step history. That is a much better basis for a release decision than “the CI job is green.”
The infrastructure drift detection problem and the environment promotion problem are two sides of the same coin: both are about maintaining confidence that what is running matches what you intended. Kargo brings that confidence to the promotion layer in a way that scripts and CI jobs never quite managed.
As platform engineering matures in the AI era, the expectation is that promotion pipelines will become more automated: more verification signal, more policy gates, and eventually AI-assisted analysis of deployment health. Kargo’s extensible Custom Steps model positions it well for that future. The teams I know who are investing in Kargo now are building the foundation for a level of release automation that most organizations are still months away from needing. That is usually a good sign that the tooling is worth learning.
Get Cloud Architecture Insights
Practical deep dives on infrastructure, security, and scaling. No spam, no fluff.
By subscribing, you agree to receive emails. Unsubscribe anytime.
