The previous four clusters are about tools. This one is about the decisions that outlive them.
A team that adopts Terraform, then Kubernetes, then a GitOps controller, then something that does not exist yet, will make the same set of architectural choices each time: where the boundaries go, who owns what, how a change reaches production, and how anybody knows whether reality still matches the declaration. Those choices are the subject here, and they are why this cluster is last — you need the tools in view before the shape of the problem is visible.
Start with monorepo versus polyrepoWhat this cluster answers
Section titled “What this cluster answers”The organising idea
Section titled “The organising idea”A repository boundary is a permission boundary, a review boundary, a CI boundary and a blast-radius boundary at the same time.
You cannot move one without moving the others, and most repository architecture arguments are really arguments about which of the four somebody is optimising. A platform engineer worried about blast radius wants more repositories. A developer worried about coordination wants fewer. Both are right about their own concern.
That framing makes the trade-offs legible:
| More repositories | Fewer repositories |
|---|---|
| Smaller blast radius per change | Atomic cross-cutting changes |
| Cleaner permission separation | Simpler permission model to reason about |
| Independent CI, faster per run | One CI configuration to maintain |
| Independent release cadence | Consistent versions by construction |
| Harder to change shared things | Easy to change shared things — including by accident |
| Discovery problem | Navigation problem |
Monorepo versus polyrepo works through this with scenarios rather than a verdict, because the answer genuinely depends on team size, ownership structure and how often changes cross boundaries.
Promotion as a first-class workflow
Section titled “Promotion as a first-class workflow”A vertical sequence: a validated change; a promotion pull request that references it; an environment diff showing exactly what will change; approval by an accountable person; merge; and automation or reconciliation applying it.
The property that makes this work is that a promotion pull request changes a reference, not content. An image digest, a chart version, a module tag, a commit SHA. The diff is one or two lines, which sounds trivial and is actually the whole point: a reviewer can see precisely what is moving, and the artifact reaching production is byte-identical to the one that was tested.
Infrastructure promotion with pull requests covers generating those pull requests automatically, and the failure modes — chiefly promotion pull requests nobody reviews because they always look the same.
Ownership is not enforcement
Section titled “Ownership is not enforcement”The distinction that catches the most teams.
CODEOWNERS is metadata. It says who owns a path and causes review requests to be routed. On its own it blocks nothing.
A ruleset or branch protection rule is enforcement. “Require review from Code Owners” is a separate setting, and without it CODEOWNERS is a courtesy.
Teams add the file, watch reviewers get requested, and reasonably conclude the control is in place. CODEOWNERS for infrastructure covers the pairing, and the ownership patterns that actually work for networking, security, production environments and workflow files.
Policy, and where it belongs
Section titled “Policy, and where it belongs”Three places to express a rule, with different guarantees:
In a document. Zero enforcement. Useful for explaining why.
In CI. Enforced for anything that goes through the pipeline. Bypassable by anything that does not.
At admission. Enforced at the API, regardless of how the change arrived. The only option that survives somebody running kubectl apply directly.
Policy as code covers writing rules as reviewable, tested, version-controlled artifacts — and the layering question, because a rule that only runs in CI protects you from mistakes and not from bypass.
Drift is not one thing
Section titled “Drift is not one thing”Detecting a difference between declaration and reality is a different problem in each tool, and the useful distinction is between detecting drift and automatically correcting it.
Detection tells you something changed outside the process. Always valuable.
Automatic reconciliation puts it back. Valuable when the declaration is authoritative; actively harmful when somebody is mid-incident and the controller keeps reverting their fix.
Infrastructure drift detection covers the cross-tool view; GitOps drift and reconciliation covers the Kubernetes-specific operational model, including how to make an emergency change without fighting your own controller.
Decisions this cluster forces
Section titled “Decisions this cluster forces”Six questions, each with a lesson. None has a universal answer, and a team that has never explicitly answered them has answered them by accident.
Where do repository boundaries go? By ownership, by lifecycle, or by blast radius — and those three do not always agree.
Does each environment get a repository, a directory or a branch? Environment repositories covers all three, including why branch-per-environment is the option that looks cleanest and causes the most trouble: merges between long-lived branches accumulate conflicts, cherry-picks lose history, and “which branch is production actually on” becomes a question people get wrong.
How does a change reach production, and what does a reviewer see when it does?
Who must approve what, and is that a preference or a rule?
Where are the rules written, and can they be bypassed?
When reality diverges from the declaration, what happens — an alert, a ticket, or an automatic correction?
Scale changes the answers
Section titled “Scale changes the answers”Repository architecture that works for four engineers stops working for forty, and the failure is gradual enough that nobody notices the transition.
A small team should default to fewer repositories. Coordination cost is low because everybody talks to everybody, and the discovery problem is trivial. A single infrastructure repository with clear directories is a good, boring answer that many teams abandon too early.
A growing team starts feeling the CI cost — every change plans everything — and the review cost, because reviewers no longer recognise most of the diff. That is the signal to introduce path-scoped ownership and change detection before splitting anything.
A large organisation needs boundaries that match team boundaries, because a repository that four teams change is a repository where nobody feels responsible. This is where module and environment repositories earn their overhead.
A platform team inverts the question entirely: rather than deciding how to structure one estate, it decides what structure to offer, as templates and reusable workflows other teams instantiate.
The trap at every stage is copying the architecture of an organisation ten times your size because their engineering blog described it. Their structure solves coordination problems you do not have, at a cost you will feel immediately.
The capstone
Section titled “The capstone”Platform engineering with Git is where the pillar’s threads are tied together: Git as the interface between developers who want an environment and a platform team that has to be able to say yes safely, repeatedly and without becoming a ticket queue.
Templates, reusable workflows, versioned modules, self-service pull requests, policy and reconciliation — every one of them appears earlier in this pillar as a technique. The capstone is about assembling them into something a team can actually operate.