Code Ownership
Somebody has to be accountable for each part of the system, and the mechanism that achieves that is the same mechanism that creates silos. The tension is real; pretending it is not is how both failures happen.
The requirement, the obvious build, and why it breaks
Every lesson starts where the work starts: someone asked for something, and the first implementation that comes to mind survives until the requirement changes.
How do I get clear accountability for every part of the codebase without producing a team nobody else can change code around?
A bug in the shared notification module has been open for three weeks. Three teams use it, nobody has fixed it, and every team believes one of the others owns it.
Everyone owns everything. Collective code ownership means anyone can change anything, which keeps the team flexible and avoids bottlenecks.
Everyone owning everything is indistinguishable from nobody owning anything the first time something needs sustained attention rather than a quick fix.
- Everyone owning everything is indistinguishable from nobody owning anything the first time something needs sustained attention rather than a quick fix.
- The three-week bug is the archetype: it is nobody's emergency, so it stays open, and each team reasonably prioritises the work they are accountable for.
- Quality drifts fastest where accountability is weakest, and shared modules are exactly where it is weakest — which is why the most-imported code in a repository is so often the worst.
- It also removes the person who knows *why*. A module with no owner has no one carrying the design rationale, so every change re-derives it or ignores it (Decision Records).
- And the opposite failure is just as real. Strict ownership with mandatory approval turns every cross-cutting change into a queue, teaches teams to duplicate rather than wait, and concentrates knowledge exactly where you least want it concentrated (Bus Factor).
What limits the solution, and what must never stop being true
This domain leads with these two. A design that ignores its constraints is not a design, and an invariant nobody named is one nothing is protecting.
- The teams are real teams with real backlogs; accountability that is not on somebody's plan is not accountability.
- Some modules genuinely need expertise to change safely — payments, auth, the migration system — and letting anyone edit them is not an option (Trust Boundaries).
- Whatever mechanism is chosen has to work when the owner is on holiday, which is most of the time for at least one owner.
- Every file in the repository has a named owner who can be reached. Unowned code is code that decays without anyone noticing (What Technical Debt Actually Is).
- No change is blocked indefinitely by the unavailability of one person; the mechanism must have a defined path when the owner does not respond.
- Ownership is about accountability for the design and its quality — never about permission to type. Those are separable and conflating them is what produces silos.
Who owns what, and where the seams fall
Responsibilities decide boundaries; boundaries decide what an interface has to say.
- The owner owns the design of the module, the review of changes to it, its quality over time, and answering questions about it. Not typing every change.
- The contributor owns making the change well and involving the owner early enough that a design objection is still cheap to act on (Review as Design Feedback — and Why It Arrives Too Late).
- The organisation owns making ownership real: time on the owner's plan for review and maintenance, or the ownership is nominal and will be discovered to be so during an incident.
- Somebody owns the ownership record itself. A stale owners file naming three people who left is worse than none, because it stops the search rather than starting it.
- Ownership boundaries should coincide with module boundaries, or reviews route to people who cannot judge the change (Internal Module Contracts).
- Where they cannot coincide — a cross-cutting concern like logging or auth — the honest answer is a named owner for the mechanism and explicit freedom for callers, rather than pretending the boundary is clean.
- The strongest distinction available: *write access* is a security boundary, *review approval* is a quality boundary, and *accountability* is an organisational one. Most silo problems come from implementing all three with the same mechanism (Least Privilege as a Design Decision).
The module nobody owns, examined
The three-week bug is worth looking at through the responsibility device, because the finding is not that the module is badly written. It is that its change triggers belong to people its accountability does not.
Notice that the verdict is not "give it to a team". Ownership without allocated time produces the same bug with a name on it, which is a worse outcome because it looks solved.
- — The templates for every transactional message
- — Which provider is used per channel and per region
- — The rate limits and the quiet-hours policy
- — Which notifications are legally required and cannot be suppressed
- — Renders templates
- — Chooses a channel and a provider
- — Enforces quiet hours and rate limits
- — Records delivery for audit
- — Two external providers
- — The user preferences store
- — A template engine
- — The clock, for quiet hours
- — Marketing changes copy
- — A provider changes its API or is replaced
- — Compliance changes what may be suppressed
- — A product team adds a new notification type
- — Someone reports that quiet hours are wrong in a new timezone
Five change triggers belonging to four different groups, and an accountability structure that names none of them. The three-week bug is not a prioritisation failure by any individual team — each of them correctly prioritised the work they are answerable for. The fix is two-part and both parts are necessary: name an owning team *and* put maintenance on its plan, then split off the part that is really product-owned. The per-notification templates and types belong to the teams that send them; the mechanism — channels, providers, quiet hours, audit — is the part that needs one owner. Assigning the whole thing to one team without that split just moves the queue (Separation of Concerns).
Three mechanisms, usually implemented as one
Almost every silo complaint traces back to a single conflation: write access, review approval and accountability are three separate mechanisms with three different purposes, and most tooling makes it easy to implement all of them with one rule.
Separating them is cheap and it resolves most of the tension in this lesson. Anyone may contribute anywhere; the owner reviews; and write restriction is reserved for the small set of paths where a mistake is a security or compliance event rather than a bug.
| Trigger | Symptom | Cause | Response |
|---|---|---|---|
| Write access is restricted to the owning team | Consumers stop fixing bugs in shared code and work around them locally | Permission was used to express accountability | Open write access; keep review required. The accountability is in the approval, not in the ability to type (Duplicate Knowledge). |
| Review is required with no time bound | Cross-team changes sit for two weeks; teams start forking | Ownership became a throughput dependency nobody planned for | Add a named escalation after N days. Publish the wait times, because the number is what makes the problem arguable. |
| Accountability is assigned without time allocated | The module has an owner and the bug is still open | Ownership was recorded, not resourced | Either allocate maintenance capacity or reassign it honestly. A false owner stops the search for a real one. |
| Ownership is per-person | Everything routes to one engineer, who is also the reason releases go smoothly | The record names an individual, and individuals go on holiday and leave | Own by team, rotate the reviewer within it, and treat single-reviewer modules as a tracked risk (Bus Factor). |
| The owners file is not maintained | Reviews route to a team that was reorganised out of existence a year ago | Reorganisations do not generate pull requests | A CI check that every owning team still exists, plus an ownership pass as a standing item in every reorganisation. |
What the record should actually say
The mechanism most teams already have is a path-to-team file. What separates a useful one from a decorative one is not the paths but the three pieces of information around them: who to escalate to, how long to wait, and what the restriction actually is.
It should be short. An ownership record that needs a table of contents is describing a structure that nobody can hold in their head, which is a finding about the structure.
1# Owners route reviews. They do NOT restrict who may open a PR.2# If an owner has not reviewed in 3 working days, the fallback may approve.3 4/billing/ @team-billing fallback: @team-platform5/checkout/ @team-checkout fallback: @team-billing6/catalog/ @team-catalog fallback: @team-checkout7/notifications/ @team-platform fallback: @team-checkout8 # mechanism only. Templates live with the sending team.9/platform/ @team-platform fallback: @team-billing10 11# WRITE-RESTRICTED. Not a silo — a control. No fallback by design.12/auth/keys/ @team-security restricted: true13/billing/ledger/ @team-billing @team-finance restricted: true14 # double approval required: regulatory, reviewed annually15 16# Reviewed: 2026-06-01. Next review: at the next reorg, or 2026-12-01.Three things make this record real rather than decorative: the fallback with a stated wait, the explicit statement that ownership does not restrict contribution, and the review date. Remove any one and it degrades into routing that nobody trusts. The two restricted paths are also doing real work by being few — a file where half the paths are restricted has stopped distinguishing controls from preferences (Least Privilege as a Design Decision).
How to build it
Most important first.
- Write ownership down, in the repository, per path, with a team rather than a person. Teams survive holidays and departures; individuals do not (Docs Close to Code).
- Separate the three concerns deliberately: anyone may open a pull request anywhere; the owner reviews; only a small set of genuinely sensitive paths restricts write access at all.
- Prefer *review required* to *change forbidden*. The first spreads knowledge in both directions; the second concentrates it and produces workarounds (Knowledge Sharing).
- Give every ownership rule an escalation path with a time bound: if the owning team has not reviewed within N days, a named second team may approve. Without this, ownership becomes a way for a busy team to block the organisation.
- Rotate deliberately. An owner who has held a module for three years and reviews every change to it is a single point of failure the org chart cannot see (Bus Factor).
- Audit the record on a schedule. Ownership files rot faster than code, because reorganisations do not produce pull requests.
What the next change costs
The field this whole domain exists for. A structure is only better if it makes the change after this one cheaper — and it is worth saying which changes it does not help.
- With no ownership: a shared-module bug costs three weeks of nobody, then an escalation, then whoever is least busy learns the module from scratch. The cost is unbounded and mostly latency.
- With owner-reviews-but-anyone-contributes: a change costs the contributor's work plus one review round, typically a day of latency. The next change by the same contributor is cheaper, because they learned the module during review.
- With owner-must-implement: the change costs a ticket in another team's backlog, which is a sprint at best, and the contributor learns nothing. The change after that costs exactly the same, forever — this is the version that does not amortise.
- The escalation path is what bounds the worst case. Without it, the cost of any change is bounded by the least available owner, and that number is not one your planning can see.
- Clear ownership buys accountability and costs throughput: every cross-cutting change now queues behind somebody else's review capacity.
- Collective ownership buys throughput and costs sustained quality in exactly the shared modules that matter most.
- The middle — anyone contributes, owner reviews — is what most teams should do, and it costs a real review latency on every cross-team change plus the discipline to keep the record current.
What can go wrong
- The owners file is written once during an initiative and never updated, so reviews route to people who left, and the escalation path is "ask in the general channel".
- Ownership is used as a veto. A team blocks changes it dislikes for reasons unrelated to quality, and there is no path around it, so consumers fork or duplicate (Duplicate Knowledge).
- One person becomes the de facto owner of everything hard, is on every review, and is the reason the team is fast — until they are not there (Bus Factor).
- Ownership is assigned but not resourced, so the owning team is accountable for a module with no time allocated to it, which produces the three-week bug with an owner's name on it.
- The mitigation fails in its own way: an escalation path with a time bound gets used routinely, ownership becomes advisory, and you are back to collective ownership with extra ceremony.
- The ownership record depends on the folder structure to express itself, which is one more reason the tree should follow the seams (Repository Structure).
- It depends on the review tooling to route automatically; ownership that requires the contributor to guess who to ask is ownership that is exercised inconsistently.
- It creates an organisational dependency in the direction of the owner: every consumer of a module now depends on that team's review capacity, which is a throughput dependency nobody plans for.
- "Collective ownership does not work." It works well in a single team of six who all touch everything and talk daily. It stops working when the people who could fix a module and the people who feel responsible for it are different sets (When Design Does Not Pay).
- "Ownership means only we may change it." That is the silo, and it is a choice, not an implication. Review-required with open contribution gets the accountability without it.
- "An owners file is ownership." The file is routing. Ownership is time on a plan, and a file without it produces the three-week bug with a name attached, which is worse because it looks solved.
- "Individual owners are clearer than teams." They are clearer and they are fragile. Naming a person creates a single point of failure and a career-shaped incentive to keep the knowledge (Knowledge Sharing).
- god-object
- shotgun-surgery
Testing it, and how it ages
- Test the record, not the intention: a CI check that every path matches an ownership rule, and that every named team still exists.
- A periodic report of pull requests that waited more than N days for an owner's review is the closest thing to a test of whether ownership is real or nominal.
- For sensitive paths where write access is genuinely restricted, an access review on a schedule — this one is Security's mechanism applied to source (Designing for Security).
- Ownership follows the org chart with a lag of about one reorganisation, and the lag is where the failures live. Every reorganisation should include an ownership pass, and almost none do.
- Modules accumulate owners over time — a payments module owned by payments, then by payments and compliance, then by three teams — and multi-owner modules are where review latency compounds.
- The end state to watch for is a module owned by a team that no longer uses it. That is the clearest signal available that the boundary and the org chart have drifted apart (Revisit Triggers).
Where this applies
This domain's advice is contested more than most. These labels say what each claim is specific to — and where CONTESTED appears, the note gives the strongest form of the opposing view rather than a caricature.
- SCALE-SPECIFICAt one team of six, collective ownership is not a compromise, it is correct: everyone touches everything, the review routing is a conversation, and an owners file adds friction with no benefit. The mechanism starts earning its keep when the people who *can* change a module and the people who *feel responsible* for it are different sets — usually the second or third team. At a hundred teams the problem inverts again: the constraint becomes review capacity and the interesting design is the escalation path, not the ownership. Applying hundred-team ownership machinery to a six-person team is one of the most reliable ways to make a small team slow.
- CONTESTEDThe strongest case for strict individual ownership, made honestly: quality is a function of somebody caring, and caring does not distribute. Advocates point to long-lived open-source projects with a single maintainer per subsystem, where the design coherence is visibly better than in collectively-maintained equivalents, and argue that review-by-owner is a weaker version that produces committees. The counter is that this model is chosen by people who can afford to wait for the maintainer, which a product team usually cannot, and that it optimises coherence at the direct expense of bus factor.
- DOMAIN-SPECIFICWhere a mistake is regulatory or safety-critical — payments, clinical data, aviation, key material — restricting who may approve a change is not a silo, it is a control, and the escalation path must not exist. That inverts the main advice in this lesson and the distinction is whether the restriction protects a real invariant or somebody's preference.
Where the depth lives
This domain teaches the codebase-level structure and hands the rest off.
- — System Design — service ownership and code ownership are usually assumed to be the same thing, and the failure mode is a service owned operationally by one team whose source is maintained by another.