The repository is part of the control plane
In GitOps, a merge is not merely documentation; it is a request to change a running system. That makes repository design an operational concern. A reviewer should be able to answer what changes, where it changes, and what reconciler will apply it without mentally executing a maze of templates.
Favor structures that match the questions people ask during reviews and incidents: Which workloads run in this environment? Which version is selected? Where is this shared capability introduced? Which file would I revert? A layout that answers those questions quickly is more valuable than one that minimizes line count.
Separate intent from reuse
Reuse is useful, but it should not erase intent. Keep small components for genuinely repeated behavior and assemble them in environment-specific entry points that remain readable. When every deployment requires tracing five bases and three patches, the abstraction is charging more than it saves.
Prefer components that are
- Focused on one capability or policy.
- Safe to include without hidden side effects.
- Versioned or changed with clear blast-radius awareness.
- Easy to render and inspect in isolation.
Avoid inheritance trees built only to remove duplication. Repeating a small amount of declarative configuration can be cheaper than creating a dependency graph nobody can reason about under pressure.
Can a reviewer predict the affected resources from the changed paths before running any tooling? If not, the repository is hiding too much.
Keep reconciliation predictable
Declare dependencies explicitly when one resource must become ready before another. Separate infrastructure provisioning, platform services, and workloads when they have different owners or recovery characteristics. Avoid circular dependencies between repositories and reconcilers.
Pin versions that must be reproducible. Automate updates through reviewable changes instead of silently following mutable tags. Treat generated manifests as build output: either keep them out of version control or define exactly how they are regenerated and reviewed.
Make health and failure states visible. A reconciler should report which object failed, what revision it attempted, and whether it will retry. Operators should not need direct cluster access merely to discover that a referenced secret, source, or namespace is missing.
Design for recovery
A useful repository supports two recovery paths: revert a known-bad change, and rebuild an environment from declared state. Practice both. Confirm that bootstrap dependencies are documented, credentials are obtainable through the approved process, and recovery does not depend on a workstation that only one person can operate.
Before a structural refactor, render old and new trees and compare resources by identity and meaningful fields. File moves that preserve content should be treated as renames; configuration rewrites need behavioral comparison.
- Environment entry points are obvious and stable.
- Shared components remain small and single-purpose.
- Version changes appear as explicit reviewed diffs.
- Rendered output is checked before reconciliation.
- Dependencies and reconciliation order are visible.
- Revert and rebuild procedures are exercised.