> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Repo Design That Works Apps Infra Environments Promotion

> Guide to structuring GitOps repositories by separating app and platform configs, using base and overlays, choosing mono versus multi repo, and defining auditable environment promotion patterns.

GitOps prescribes "put everything in Git" — great guidance, but it doesn't tell you how to organize those files. Without a deliberate structure, your GitOps repo quickly becomes the YAML equivalent of a junk drawer: hard to understand, risky to change, and slow to onboard new engineers.

This guide shows a practical, scalable repo layout and promotion patterns that separate concerns, clarify ownership, and make promotions explicit and auditable. By the end, you’ll have a simple reference architecture you can apply right away.

![A presentation slide titled "Learning Objectives." It lists three points about repo structure for GitOps: why it matters, monorepo vs multi-repo tradeoffs, and designing environment-specific configs using base + overlays.](https://mintcdn.com/kodekloud-c4ac6d9a/seqLTE3JlSrVAtw9/images/Prep-Course-Certified-Cloud-Native-Platform-Engineering-CNPE/GitOps-and-Continuous-Delivery/Repo-Design-That-Works-Apps-Infra-Environments-Promotion/gitops-repo-structure-learning-objectives.jpg?fit=max\&auto=format\&n=seqLTE3JlSrVAtw9\&q=85\&s=ba604a55838937827a0aa38f77ed9feb)

Example: how a small repo becomes unmanageable
A typical story: one developer drops a few YAMLs into a repo. Over time files multiply and names diverge — `-prod`, `-staging`, `BACKUP`, `DO-NOT-DELETE`. New hires spend days asking "which file is the truth?"

Example of a flat, unstructured repo:

```text theme={null}
my-company-k8s/
├── api-deployment.yaml
├── api-deployment-prod.yaml
├── api-deployment-prod-v2.yaml
├── api-deployment-prod-BACKUP.yaml
├── web-service.yaml
├── web-service-staging.yaml
├── DO-NOT-DELETE.yaml
├── helm-values.yaml
├── helm-values-prod.yaml
└── old-stuff/
```

Symptoms and impact of an unstructured GitOps repo

| Failure mode | Typical symptoms | Impact |
| - | - | - |
| Multiple versions with no single source of truth | Many similarly named manifests (prod-v2, BACKUP) | Confusion; accidental rollbacks or drift |
| Environment confusion | Dev/staging/prod content mixed in same folders | Risk of deploying wrong config to prod |
| No promotion path | No standard way to move a change from dev → prod | Manual, error-prone promotion; poor audit trails |
| Apps and infra mixed | Platform and app changes in same files | Teams step on each other; reviews and access control are hard |

Why this happens: Git is flexible but neutral. You must design the layout and rules.

Separate application code from GitOps configuration
Application source and GitOps config have different lifecycles, owners, and review processes:

* Application code: frequent commits, feature reviews, CI pipelines.
* GitOps config (manifests, Helm values, Kustomize overlays): less frequent, security and platform review, different change cadence.
* Ownership: dev teams typically own app repos; platform teams own cluster-level and platform config.

Keep them in separate repositories to reduce noise, limit blast radius, and enable distinct access controls.

Example repo separation
Code repo (application):

```text theme={null}
src/
tests/
Dockerfile
```

GitOps config repo:

```text theme={null}
base/
overlays/
values/
```

This prevents frequent code commits from triggering unrelated GitOps reconciliations and enables separate review workflows.

Helpful resources:

* Kubernetes Basics: [https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/)
* Helm: [https://helm.sh/](https://helm.sh/)
* Kustomize: [https://kubectl.docs.kubernetes.io/guides/introduction/kustomize/](https://kubectl.docs.kubernetes.io/guides/introduction/kustomize/)

Monorepo vs multi-repo for GitOps configs
Deciding between storing all GitOps configs in a single repository or splitting them depends on size, team boundaries, and operational needs.

| Strategy | Pros | Cons | When to use |
| -: | - | - | - |
| Monorepo | Single source of truth; atomic cross-app changes; easier standards enforcement | Coarse-grained access control; can get large | Small-to-medium orgs, when teams share standards |
| Multi-repo | Fine-grained access control; team autonomy; smaller repos | Harder cross-app changes; potential standards drift | Large orgs with strong team boundaries and many services |

Recommendation: start with a monorepo for small-to-medium teams. Consider migrating to multi-repo when you exceed \~20–30 services or need stricter access boundaries.

Example layouts

```text theme={null}
# Monorepo style
gitops-configs/
├ apps/api/
├ apps/web/
└ clusters/[dev|stg|prod]

# Multi-repo style (examples)
api-gitops/
web-gitops/
platform-gitops/
```

Manage environment-specific configuration with base + overlays (Kustomize pattern)
A robust pattern is to store canonical manifests in a `base/` directory and keep per-environment differences in small `overlays/` folders. This mirrors the Kustomize approach and makes diffs small and auditable.

Example structure:

```text theme={null}
api/
 ├─ base/
 │  ├─ deployment.yaml
 │  ├─ service.yaml
 │  └─ kustomization.yaml
 └─ overlays/
    ├─ dev/
    │  └─ kustomization.yaml
    ├─ staging/
    │  └─ kustomization.yaml
    ├─ prod/
    │  ├─ kustomization.yaml
    │  └─ replicas-patch.yaml
```

Common environment differences

* Replicas (dev: 1, staging: 2, prod: 5)
* Resource requests/limits (small in dev, larger in prod)
* Secret references (each environment uses its own secret names)
* Ingress/URLs (e.g., `api-dev.example.com` vs `api.example.com`)

![A presentation slide titled "Environment Structure" showing a numbered checklist of deployment settings. Items include Replicas (dev:1, staging:2, prod:5), Resources (CPU/Memory requests and limits), Secrets refs (different secret names per env), and Ingress/URLs (api-dev.example.com vs api.example.com).](https://mintcdn.com/kodekloud-c4ac6d9a/seqLTE3JlSrVAtw9/images/Prep-Course-Certified-Cloud-Native-Platform-Engineering-CNPE/GitOps-and-Continuous-Delivery/Repo-Design-That-Works-Apps-Infra-Environments-Promotion/environment-structure-deployment-checklist.jpg?fit=max\&auto=format\&n=seqLTE3JlSrVAtw9\&q=85\&s=41ca51a31554440857ca722f76e857dc)

Principle: keep base configs identical; overlays contain only environment deltas. If your prod overlay is dozens of lines long, refactor — the overlay should be minimal and declarative.

Keep overlays minimal. Express only environment deltas (replicas, resource sizes, secret names, URLs). Avoid duplicating the entire manifest in overlays.

Promotion strategies — how changes flow between environments
Choose a promotion pattern that matches your team’s workflow and compliance needs. Common patterns:

1. Branch-based
   * Each environment maps to a branch (`dev`, `staging`, `main`/`prod`).
   * Promotion = merge from lower env branch to higher env branch.
   * Pros: conceptually simple. Cons: branch management overhead.

2. Directory-based
   * Each environment has its own directory (`envs/dev`, `envs/staging`, `envs/prod`).
   * Promotion = open a PR that updates the next environment's directory.
   * Pros: Git-native audit trail via PRs; works well with CI checks.

3. Image tag–based (often combined with directory-based)
   * Environments reference image tags in overlays/values.
   * Promotion = update the image tag in the next environment’s file.
   * Pros: clear traceability of which image is running where; compatible with automated deployment pipelines.

Summary example:

```text theme={null}
# Branch mapping
dev → dev
staging → staging
main → prod

# Directory layout
envs/dev/
envs/staging/
envs/prod/

# Image tag promotion example
dev:  image: myapp:abc123
stg:  image: myapp:abc123
prd:  image: myapp:def456
```

Recommended pattern in practice
Directory-based layout combined with image tag promotion provides a clear, auditable promotion path: PRs update the environment directory or the referenced image tag, and GitOps tooling applies the change to the target cluster.

Reference repo structure (recommended)
A straightforward, opinionated top-level layout that clarifies ownership and purpose:

```text theme={null}
apps/          # application workloads, owned by dev teams
  ├ app1/
  │  ├ base/
  │  └ overlays/
  └ app2/
infrastructure/ # platform components (monitoring, ingress, cert-manager), owned by platform team
clusters/       # cluster-level config (which apps + infra to deploy per environment)
  ├ dev/
  ├ staging/
  └ prod/
```

Tools like Argo CD ApplicationSets can scan these directories and generate Application resources per app/environment automatically. See Argo CD documentation for ApplicationSets and automation patterns: [https://argo-cd.readthedocs.io/](https://argo-cd.readthedocs.io/)

Benefits of this layout

* Clear ownership boundaries: developers manage app folders; the platform team manages infra.
* Consistent patterns across teams make the repo self-documenting and minimize tribal knowledge.
* Easy automation: ApplicationSets or templating tools can onboard new apps and environments quickly.

![A presentation slide titled "Environment Structure" that states a principle. It shows two panels: "Keep base configs identical" and "Overlays contain only the differences," each with a blue circular icon above.](https://mintcdn.com/kodekloud-c4ac6d9a/seqLTE3JlSrVAtw9/images/Prep-Course-Certified-Cloud-Native-Platform-Engineering-CNPE/GitOps-and-Continuous-Delivery/Repo-Design-That-Works-Apps-Infra-Environments-Promotion/environment-structure-base-identical-overlays-differences.jpg?fit=max\&auto=format\&n=seqLTE3JlSrVAtw9\&q=85\&s=b3e585642cefe0ac5f21fb2038c1b063)

Four key takeaways

* Separate code from config: different lifecycles, owners, and review processes mean separate repos and access controls.
* Use base + overlays to avoid duplication and keep per-environment diffs small and auditable.
* Define and document a clear promotion path (directory-based + image tag promotion is a practical default).
* Separate apps from infrastructure so teams can operate independently and safely.

With a small, consistent structure and explicit promotion rules, your GitOps repo becomes a readable, auditable, scalable source of truth.

> **[Watch Video](https://learn.kodekloud.com/user/courses/prep-course-certified-cloud-native-platform-engineer-cnpe/module/dff5382b-dbe7-4cac-bd2b-d5a47028945e/lesson/a1fa35aa-97ac-4a69-8a50-67c59699ff12)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.