Flux is not the variable in this decision. Flux stays.
The decision is where delivery state should be promoted and fetched from: Git (classic GitOps) or OCI artifacts (OCI-backed GitlessOps). That choice changes more than pipeline ergonomics. It changes rollback behavior, observability of the control path, and how cleanly ownership boundaries hold up under production pressure.
At a Glance
Status. Contextual.
Audience. Tech leads, senior fullstack engineers, and platform-minded engineers operating Flux in production.
Assumes. A Kubernetes deployment baseline already exists, Flux is already the reconciler, and CI can produce immutable images and tags.
Not for. Teams evaluating Flux adoption, imperative CI-to-cluster deploys
(kubectl apply from CI), or beginner Kubernetes intros.
Maturity target. Primary L3, requires L2, and moves toward L4 (with
signed/provenance-aware OCI artifacts and policy checks).
Improves. Desired-state placement for app delivery, promotion consistency, rollback ergonomics, reconciliation observability, and ownership boundaries.
Does not solve. Weak Kubernetes runtime baselines, app-level observability gaps, or release discipline issues on its own.
Table of contents
Open Table of contents
Context
Flux is already the standard reconciliation engine, and Kubernetes is the execution platform. That part is settled. The open question is not whether to reconcile, but where the reconciled delivery state should live and how it should be promoted between environments.
In practice, the OCI registry is already part of the artifact backbone for application images. That makes OCI a natural candidate for delivery-state bundles as well, but adopting it for deployment state changes the operating model: review flow, rollback mechanics, source observability, and failure behavior all shift.
The goal is not to choose the cleanest pattern on paper. It is to choose a model that remains understandable and operable when rollouts fail, promotions need to be reversed quickly, and multiple teams share the same delivery system.
Assumptions
- CI can build once and promote immutable artifacts.
- Environments are isolated and reconciled independently.
- The team can operate both Git and OCI registries reliably.
- “GitlessOps” in this article means OCI-backed desired-state artifacts reconciled by Flux, not imperative CI deploys to the cluster.
Problem Statement
We already standardized Kubernetes delivery on Flux. The decision is whether Flux should reconcile application delivery state from Git (Git-backed GitOps) or from OCI artifacts (OCI-backed GitlessOps).
The chosen model must improve promotion consistency, rollback ergonomics, observability of reconciliation and rollouts, and operational clarity without introducing more platform complexity than the team can sustain.
The hidden part of the decision is this: are we using Git as both the review system and the delivery transport, or do we separate those concerns and use OCI as the transport for promoted deployment state?
Decision Criteria
The comparison is not “which tool is nicer.” It is a production operating decision, so the criteria are operational first:
- Promotion path clarity (
dev -> preprod -> prod) - Review and audit trail quality
- Rollback speed and operator ergonomics
- Reconciliation observability (source fetch, errors, lag, drift)
- Deployment observability (rollout health, failure signals)
- Artifact immutability and provenance readiness
- Operational burden and ownership boundaries
- Failure behavior under Git or registry incidents
Options Considered
All three options keep Flux as the reconciler. What changes is the source of desired state, the promotion mechanism, and the operational behavior that follows.
Comparison at a glance
| Option | Best fit | Main strength | Where it starts to hurt |
|---|---|---|---|
| Git-backed GitOps | Teams centered on Git review flows | Reviewability and auditability in Git | Promotion turns into commit choreography |
| OCI-backed GitlessOps | Teams optimizing promotion/rollback ergonomics | Immutable promoted deployment bundles | Visibility and traceability degrade without good tooling |
| Hybrid (Git + OCI) | Teams separating platform intent from app release transport | Better boundary alignment | Becomes inconsistent without explicit ownership contracts |
Option A - Git-backed reconciliation with Flux (classic GitOps)
This is the most familiar model and the easiest one to explain to teams already comfortable with merge requests and Git-based review. It keeps the final delivery state visible in Git, which is a real advantage when auditability and human-readable diffs are part of daily operations.
Another practical advantage is precision. In Git-backed flows, the deployment state is static text: image tags, patches, and environment-specific values are explicit, reviewable, and directly verifiable from the repository itself. When an operator asks “what is supposed to be deployed?”, Git usually answers that question without extra tooling.
In practice, this model starts to hurt when promotion becomes “commit choreography.” The problem is rarely Flux itself. The problem is the amount of workflow logic that accumulates around Git writes, branch rules, repo topology, and automation permissions.
Operationally, Git-backed reconciliation is usually easier to reason about at
the beginning because the review system and the delivery source are the same
thing. Flux source and Kustomization health are also straightforward to
inspect. The hidden cost is CI automation scope: once CI starts writing back to
Git for promotions, permission boundaries and repo conventions matter a lot.
CI can still inject metadata in this model, but only by writing it back into
Git (annotations, labels, generated files), which often creates noisy diffs and
mixes release bookkeeping with long-lived configuration intent.
There is also an ownership split that can fail quietly. In many teams, a large
part of what can be deployed is constrained on the Flux side (sources,
Kustomization wiring, repository topology) and is managed by platform/SRE,
while the application deployment definition itself lives with the app team
(often via Kustomize overlays). If those contracts drift, the breakage is not
always visible at review time.
Git-backed automation also creates recurring auth friction: CI needs write access to the deployment repository for promotions, and token rotation/permission renewal becomes part of the operating cost.
This option is strongest when Git review quality is the dominant constraint and teams are willing to invest in clean repository topology.
Failure modes to watch:
- Promotion commits become fragile or hard to audit under pressure
- Repo sprawl couples app and platform changes unintentionally
- Git source availability blocks new reconciliations
- CI Git write access becomes broader than intended
Option B - OCI-backed reconciliation with Flux (GitlessOps via OCI)
This model treats deployment state more like a promoted artifact than a mutable repository branch. It aligns well with build-once/promote-many practices and usually improves rollback ergonomics, because operators are reasoning about a known bundle reference rather than reconstructing state from a chain of commits.
The trade-off is visibility. OCI-backed delivery can be operationally strong and still be harder to review if the team has poor tooling or weak conventions for bundle inspection, provenance, and traceability.
What OCI-backed reconciliation buys you is cleaner promotion semantics. A deploy bundle behaves like a promoted artifact, which usually improves rollback ergonomics and aligns naturally with build-once/promote-many release flows. That is a real operational gain, not just a packaging preference.
It also changes what CI can attach to a deployment release. Because CI is producing and promoting the deploy bundle, it can embed richer release metadata (pipeline number, build/version labels, commit references, provenance links, timestamps) without rewriting Git manifests for every promotion step. This is a real advantage for traceability, especially when release orchestration spans multiple environments.
This becomes especially visible when using floating environment tags (for
example prod or preprod). In that model, the SRE-managed configuration is
mostly about aligning an environment to a deployment channel and defining how
Flux consumes it, not about enumerating which versions are deployable. The
application CI defines and promotes the actual release values by building an
artifact and updating the promoted tag/reference.
What it changes is the debugging surface. Source health becomes more
registry-centric (OCIRepository fetch/pull behavior), and artifact lifecycle
policy becomes part of rollback safety. If retention, mutability, and trace
linking are weak, the operational benefit disappears quickly.
The downside is discoverability from Git alone. Git may still describe how the bundle is consumed, but it no longer tells you the full promoted deployment state by simple repository inspection. Without external tooling (registry inspection, release metadata UI, runbooks, dashboards), answering “which version is deployed?” becomes slower than it should be.
The auth model is also cleaner in one important way: Flux/cluster-side access can be limited to registry read permissions, and CI no longer needs write access to a deployment Git repository. That creates a stronger decoupling between the code platform and the cluster control path.
In a pull-based Flux model, CI still does not need direct cluster credentials. But many teams add a signaling path (webhook, receiver, agent) from CI into the control plane to reduce polling delay or make floating-tag promotions converge faster. That extra integration path should be treated as part of the delivery system.
This option is strongest when artifact discipline is already part of the team’s operating model and Git does not need to be the transport for every promoted state change.
From a security and platform maturity perspective, OCI-backed delivery also fits well with L4 direction: signing, provenance, and policy checks attach more naturally to promoted artifacts than to “whatever is currently in a branch.” That benefit only materializes if registry RBAC, artifact mutability rules, and retention policy are treated as part of the delivery system, not registry admin details.
Failure modes to watch:
- Registry outage blocks both delivery-state fetch and image pulls
- Bundle tagging/mutability policy makes rollback unsafe
- Retention policy deletes rollback candidates
- Operators cannot inspect bundle contents fast enough during incidents
Option C - Hybrid: Git-backed platform state, OCI-backed application delivery bundles
The hybrid model is less ideologically pure, but it usually maps better to how teams actually work. Platform topology and policy tend to benefit from Git-based review, while application release bundles benefit from immutable promotion and rollback semantics.
This option only works if the boundary is explicit. Without a written contract, “hybrid” quickly becomes “inconsistent.”
The hybrid model is usually the best fit when the team already feels the trade-off in both directions: Git is excellent for reviewing platform intent, while OCI is better for distributing promoted release state. It avoids forcing a single transport to serve both long-lived policy-bearing configuration and fast-moving application release bundles.
The cost is not conceptual complexity; it is operational discipline. You need a clear contract for ownership, source types, promotion semantics, and runbooks. If that contract is weak, operators will lose time debugging the wrong control path.
This option is strongest when the organization can state, in writing, what belongs in Git and what is promoted as OCI.
It also creates a cleaner path to L4 adoption because policy-bearing platform state and signed/promoted application bundles can evolve at different speeds without forcing a single control path to carry both concerns.
Failure modes to watch:
- Boundary drift over time (“everything in OCI” or “everything back in Git”)
- Mismatched promotion semantics between teams
- Runbooks and dashboards only cover one source type
Team Boundaries and Failure Visibility
This is one of the most important differences in practice, especially when app teams and platform/SRE teams do not own the same part of the delivery path.
In Git-backed GitOps, the deployable surface is often split across two places: the application team owns the deployment definition (for example Kustomize overlays and app-specific values), while platform/SRE owns much of the Flux wiring and repository structure that determines what can actually reconcile. That split is workable, but it can fail in ways that are not immediately obvious:
- app overlay changes look valid, but the Flux source/path wiring still points to an older layout
- platform refactors repository topology or
Kustomizationwiring, and the next app promotion breaks later - image tag/value changes are correct in Git, but the expected overlay is not the one reconciled in the target environment
The problem is not “GitOps is wrong.” The problem is failure visibility across team boundaries. If ownership is split, the delivery contract must be explicit and observable.
In OCI-backed delivery (especially with floating environment tags like prod
or preprod), the boundary often shifts in a useful way. Platform/SRE config
mainly aligns an environment to a deployment channel and defines how Flux
consumes that source. The application CI owns the release values and promotion
steps: one step builds and tags the deploy artifact, another step moves the
environment tag/reference to define what should be deployed.
This reduces pressure on SRE-owned config to enumerate every deployable version, but it introduces a different visibility requirement: operators must be able to see who moved the floating tag, from which pipeline, to which digest, and when. Without that, the system is operationally fast but incident debugging becomes guesswork.
Failure visibility by model (quick reference)
| Incident question | Git-backed GitOps | OCI-backed (floating tags) | Hybrid |
|---|---|---|---|
| What version should be deployed here? | Usually visible in Git manifests/overlays (if tags are explicit) | Requires registry/release metadata tooling; Git alone is often insufficient | Git for platform intent, OCI tooling for app release state |
| Who changed deploy intent? | Git history/MR usually answers this well | CI/release metadata must expose pipeline, actor, tag move, digest | Depends on boundary; both traces must be linked |
| Where can breakage hide between teams? | Flux wiring/topology (SRE) vs app overlays/values (app team) | Environment-channel config (SRE) vs CI promotion/tag movement (app team) | In the boundary contract itself if ownership is vague |
| What auth friction shows up first? | CI write access to deployment repo (tokens/rotation/scopes) | Registry permissions and artifact policy/retention discipline | Both, unless boundaries are simplified aggressively |
| What extra path can fail silently? | Git write-back automation and repo conventions | Tag move/metadata publication and optional CI -> control-plane trigger path | Any unobserved handoff between Git and OCI paths |
Observability Lens
This is where the choice becomes real in production.
With Git-backed reconciliation, operators usually get better human review visibility but not necessarily better runtime visibility. You still need to observe Flux source health, kustomization readiness, rollout status, and the distance between “merged” and “actually reconciled.”
The upside is source-of-truth readability: if the promotion model writes exact image tags into Git, the repository itself remains a precise verification tool. The downside is metadata richness. If you want pipeline IDs, release labels, or other CI-generated context attached to the deployed state, you either accept additional Git writes (and noisier diffs) or you maintain a separate release trace system anyway.
You also need observability that matches the ownership split: when Flux wiring is managed by platform/SRE and deployment overlays are managed by app teams, alerts and runbooks must make it obvious whether a failure comes from source plumbing or from application delivery-state changes.
With OCI-backed reconciliation, the observability center of gravity shifts:
- source health becomes more registry- and
OCIRepository-centric - artifact immutability and retention policy become part of rollback safety
- traceability between bundle tag, image tag, and rollout status becomes a hard requirement (not documentation nice-to-have)
- CI can attach richer deployment metadata to the promoted bundle, but operators need tooling that surfaces it quickly
- Git alone is no longer sufficient to answer deployed-version questions in many cases
- floating tags require strong digest-level traceability, or “what moved prod?” becomes ambiguous
- if CI triggers reconciliation/refresh signals, that path needs observability too (delivery events, webhook failures, receiver health)
The practical question is not “Can we observe this?” It is “Can the on-call engineer explain a failed deployment in under five minutes, including whether the failure is in source fetch, reconciliation, manifest apply, or workload rollout?”
Decision
Use a hybrid model as the default:
- Git-backed reconciliation for platform topology, shared configuration, and policy-bearing resources
- OCI-backed reconciliation for application delivery bundles where promotion speed, immutability, and rollback ergonomics are primary concerns
The reason is not novelty. It is separation of concerns.
Flux remains the single reconciliation engine, which keeps the operational model stable. Git stays the strongest review system for long-lived platform intent. OCI becomes the distribution mechanism for promoted release state where immutability and rollback matter more than Git-native diff ergonomics.
This keeps review and distribution connected, but not collapsed into the same transport.
Accepted risks:
- Operating two source types in Flux increases runbook complexity.
- Teams must document ownership boundaries to avoid “source of truth” confusion.
Consequences
The immediate benefit is clarity: the promotion path stops being an accidental byproduct of Git workflows and becomes an explicit delivery design. For application releases, rollback ergonomics improve because operators can re-point to a known OCI bundle reference instead of reconstructing state through commit history.
The cost is operational complexity in a different place. Artifact lifecycle
management (retention, naming, immutability guarantees) becomes part of the
delivery contract. Observability must cover both Git and OCI source health, not
just Kustomization readiness. Onboarding also gets harder because the model is
more nuanced than “everything in Git.”
Longer term, the model is a better fit for L4 supply-chain hardening because OCI-backed delivery artifacts can participate in signing/provenance workflows. That only pays off if platform and app teams maintain a clear contract for what is authored in Git and what is promoted via OCI.
When This Decision Becomes Wrong
Revisit this decision if:
- The team cannot maintain clear boundaries between platform state and app release state
- Registry reliability/operations become a greater risk than Git workflow friction
- Audit/review requirements demand Git-native visibility for every promoted delivery change
- OCI bundle tooling becomes opaque enough that operators lose confidence in rollback/debugging
- The organization standardizes on a single promotion system for compliance reasons
Target Topology / Flow
This article compares two delivery-state sources while keeping Flux constant.
Option A - Git-backed reconciliation with Flux
Option B - OCI-backed reconciliation with Flux (GitlessOps via OCI)
Hybrid baseline (recommended)
- Keep platform topology and shared policy resources Git-backed.
- Promote application delivery bundles through OCI when rollback and immutable promotion are dominant concerns.
Implementation Notes
Only the minimum needed to make the decision actionable is included here.
Git-backed source (Flux)
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: app-delivery
namespace: platform-namespace
spec:
interval: 1m
url: https://git.example.com/org/app-delivery.git
ref:
branch: main
OCI-backed source (Flux)
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: app-delivery-bundle
namespace: platform-namespace
spec:
interval: 1m
url: oci://registry.example.com/team/app-delivery
ref:
tag: prod-2026-02-22.1
Reconciliation observability checks (operator-facing)
# Source health (Git and/or OCI)
flux get sources git -A
flux get sources oci -A
# Reconciliation status
flux get kustomizations -A
# Drill into failures
kubectl -n platform-namespace describe ocirepository app-delivery-bundle
kubectl -n platform-namespace describe kustomization app
kubectl -n platform-namespace get events --sort-by=.lastTimestamp
Observability expectations (minimum)
- Dashboards for Flux source health (
GitRepository/OCIRepository) andKustomizationreadiness - Alerting on reconcile failures, fetch failures, and prolonged non-ready states
- Clear correlation between promoted bundle/image tag and deployed rollout
Production Readiness Checklist
- Scope / non-goals stated
- Assumptions stated
- Promotion path documented (
dev -> preprod -> prod) - Source ownership boundaries documented (Git vs OCI)
- Registry immutability/retention policy defined for deploy bundles
- Rollback path defined and tested for both source types
- Flux source and kustomization observability in place
- RBAC validated for CI, Flux, and registry access
- Failure modes documented in runbooks
Decision Lens
Optimal if:
- You already use Flux and want to improve delivery-state promotion and rollback without abandoning reconciliation
- You can enforce artifact immutability and retention discipline in OCI
- You want Git for review and OCI for distribution
Risky if:
- Your team lacks registry operational maturity
- Ownership boundaries between platform and app delivery are unclear
- Audit expectations require Git-native review for every promoted state change
Operational burden introduced:
- Dual-source observability (Git and OCI)
- Artifact lifecycle management for deploy bundles
- Clear platform/app contract on what belongs in which control path
Revisit decision when:
- Delivery incidents repeatedly trace back to source ambiguity
- Registry operations become a larger bottleneck than Git workflows
- Compliance/policy requirements materially change the acceptable source-of-truth model