skip to content

Code Ownership & Project Boundaries

A shared repo still needs owners, so you use CODEOWNERS, per-project visibility rules, enforced module boundaries and review gates. You will learn how project tags map to teams, which is Conway's Law applied to a directory tree.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

6

In a shared monorepo hosted on GitHub or GitLab, what does a CODEOWNERS file do, and how does it change what happens when someone opens a pull request?

level: juniorimportance: must knowfreq 65%

answer

  1. glob-to-owner mapping file
  2. auto-requested reviewer
  3. branch protection = hard gate
  4. last-match-wins precedence
  5. review-only, not code enforcement

basics

~10 s

A CODEOWNERS file maps folders/files to people or teams. When a PR touches those files, the platform automatically asks the listed owners to review, and can require their approval before merge.

solid answer

~40 s

CODEOWNERS is a plain-text file (e.g. `.github/CODEOWNERS`) with glob-pattern-to-owner mappings, like `/services/payments/ @team-payments`. When a PR changes files matching a pattern, the platform auto-requests review from the mapped owner(s). Combined with a branch protection rule 'require review from code owners,' it becomes a hard merge gate: the PR can't merge without an approving review from someone in that entry. It's evaluated per-PR against the diff's touched paths, last-matching-pattern-wins on conflicts, and it only governs review requirement, not build/runtime access — it doesn't stop code from importing an owned module, and it doesn't stop someone with write access from opening the PR in the first place; it just decides who must approve it.

go deeper

for a junior

Should know CODEOWNERS exists and maps paths to reviewers; doesn't need precedence rules or the branch-protection interplay.

for a middle

Should know pattern precedence, that branch protection is needed to make it a hard gate, and how to write scoped patterns for subteams.

for a senior

Should design ownership maps for large repos (nested overrides, team vs. individual entries) and know its limits — a review gate only, not access or import control.

for a principal

Should reason about ownership-model choices across the org — single vs. per-domain CODEOWNERS files, tooling to keep them synced with team topology, and when to layer build-tool enforcement on top.

## What the file is A CODEOWNERS file is a plain-text convention (supported natively by GitHub, GitLab, and Bitbucket, and implemented independently by tools like Google's internal OWNERS files and Gerrit) that lives at a fixed path in a repository — typically `.github/CODEOWNERS`, `.gitlab/CODEOWNERS`, or the repo root — and maps **file-path glob patterns** to one or more **owners**, where an owner can be an individual username or a team/group handle. A typical line looks like `/services/payments/ @org/payments-team`, meaning any file under that directory is 'owned' by the payments team. ## How a pull request is matched The mechanism itself is simple. Whenever someone opens a pull request, the hosting platform: 1. diffs the PR against the target branch; 2. walks every changed file path; 3. for each one finds the *last* matching pattern in the CODEOWNERS file — patterns are evaluated top-to-bottom, and, like a `.gitignore` file, a later, more specific pattern overrides an earlier, more general one. The **union of owners** for all matched patterns across the whole diff becomes the set of reviewers the platform automatically requests. ## From convenience to policy By itself, that's just a convenience — it saves someone from manually figuring out who to ping. The mechanism becomes a real *policy* only when paired with a **branch protection rule**, commonly labeled 'Require review from Code Owners,' on the target branch. - **With that rule enabled**, the merge button is disabled until at least one person from every matched owner group has submitted an approving review — this is what makes CODEOWNERS a hard gate rather than a suggestion. - **Without that rule**, CODEOWNERS is purely advisory: reviewers get auto-requested, but anyone with merge permission can still merge without their approval. ## Why it exists The reason this exists is that as a codebase and organization grow, 'everyone reviews everything' doesn't scale — most engineers in a large monorepo have neither the context nor the standing to meaningfully review a change to a module they've never touched, and asking them to try produces rubber-stamp approvals or bottlenecks on whoever happens to be online. CODEOWNERS routes review responsibility to the people who actually understand a given area, automatically, without relying on the PR author to remember who that is — which matters especially for new hires and cross-team contributors who don't yet know the informal ownership map. ## The trade-off The trade-off is that CODEOWNERS only governs who must approve a merge, nothing else. - It **does not restrict who can open a PR** against those files — anyone with write access can propose the change. - It **doesn't prevent another module from importing** or depending on owned code — that's a build-time concern handled by separate tooling (visibility rules, module-boundary linting). - It **doesn't validate that the reviewer actually understood the change**; a rubber-stamp approval satisfies the gate exactly as well as a careful review. So CODEOWNERS solves the 'who reviews this' routing problem but nothing about review quality or architectural correctness. ## Failure modes Failure modes recur in a few recognizable ways. - **Individual-named owners** (`@jane` rather than `@team-x`) create single points of failure: if Jane is on leave or has left and the entry wasn't updated, every PR touching that path stalls with no automatic fallback — most platforms have no 'escalate after N days' behavior, so this needs team-based entries or a monitoring bot. - **Precedence bugs** are common: someone adds a more specific pattern below an old one expecting it to be additive, not realizing it fully overrides the earlier match, silently changing who's asked to review. - **At scale**, CODEOWNERS files often balloon to thousands of lines nobody maintains carefully, drifting out of sync with actual team boundaries after reorgs. - **Coarse ownership** over widely-shared code turns a small owning team into an organization-wide bottleneck, since every consumer's PR routes through the same reviewers regardless of triviality. ## Where the convention came from A well-known real-world instance predates GitHub's native support: Chromium and many Google-internal repositories use `OWNERS` files with essentially the same semantics — per-directory ownership, inherited down the tree unless overridden, enforced by Gerrit's review tooling before a change can land — which is part of why GitHub's CODEOWNERS feature later adopted such similar syntax and behavior.

  • What happens if two CODEOWNERS patterns match the same file?
    The last matching pattern in the file wins, the same rule .gitignore uses. Most repos put general defaults near the top and add more specific overrides below them, so it's easy to accidentally change who's asked to review by adding a new rule in the wrong place.
  • Does CODEOWNERS stop someone from importing or depending on code they don't own?
    No — it only gates PR review on file paths, not compile-time or runtime dependencies. Stopping unwanted imports is a separate concern handled by build-tool visibility rules or module-boundary linting layered on top.
  • What happens when a CODEOWNERS entry names an individual who becomes unavailable?
    The PR stalls waiting for a review that can't come from anyone else, since most platforms have no automatic escalation or fallback. This is why mature setups use team handles instead of individuals, plus a bot that flags requests stuck too long.
  • How do teams keep CODEOWNERS accurate as they reorganize?
    By treating it as living config with its own owner, adding a CI check that flags entries referencing teams or users that no longer exist, and making CODEOWNERS updates a required step of the reorg process rather than an afterthought.

Like a building directory board that says 'West wing keys held by Facilities' — anyone can walk the halls, but opening a specific door still requires sign-off from the listed keyholder.

saying these in an interview costs you the question

  • Thinks CODEOWNERS by itself blocks merges without branch protection enabled
  • Believes it enforces which packages code can import
  • Doesn't know last-match precedence, assumes first match wins
  • Assumes one CODEOWNERS entry covers a whole repo instead of directory-scoped patterns
  • Unaware it's advisory unless paired with a 'require review from code owners' branch protection setting

context

open as a page

Beyond CODEOWNERS-driven review, how do tools like Bazel visibility rules or Nx's module-boundary lint rule enforce project boundaries at build time, and why would a team want both that and human review?

level: middleimportance: must knowfreq 50%

basics

~20 s

Build tools can hard-block code from even compiling if it imports something outside its allowed visibility, unlike CODEOWNERS which only asks a human to review. Teams want both: humans catch design issues, the build catches accidental violations instantly on every change.

open as a page

A monorepo requires code-owner approval on every PR that touches a shared `libs/common-utils` package used by 30 teams. What problem does this create, and what are two ways to fix it without removing the review requirement entirely?

level: middleimportance: must knowfreq 55%

basics

~20 s

Every small change to a widely-used shared folder needs sign-off from a small owning team, so that team becomes a bottleneck. Fix it by splitting ownership into smaller pieces, or letting a wider team share the review load instead of one narrow gate covering everything.

open as a page

When carving ownership boundaries in a monorepo, why do teams try to align project/module ownership tags with the org's team structure, and what goes wrong when that alignment drifts, per Conway's Law?

level: seniorimportance: must knowfreq 60%

basics

~10 s

Conway's Law says a system's architecture tends to mirror the communication structure of the org that built it. If module ownership doesn't match team structure, changes constantly need cross-team coordination, slowing everyone down.

open as a page

A company running a large monorepo is considering locking down write access per-directory so only the owning team can push to their own service's folder, mirroring a multi-repo permission model. What are the costs of doing this, and when would you deliberately keep write access repo-wide instead?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Locking write access per folder stops accidental cross-team edits but also blocks the fast, whole-repo refactors that make monorepos useful. Many teams keep write access open repo-wide and use review requirements instead, reserving hard restrictions for a few very sensitive paths.

open as a page

In a monorepo with thousands of projects and hundreds of teams, what typically causes ownership metadata like CODEOWNERS entries and project tags to decay over time, and what governance practices keep it trustworthy?

level: principalimportance: nice to knowfreq 25%

basics

~20 s

As teams reorganize, merge, or disband, nobody remembers to update who owns old code, so some folders end up owned by teams that no longer exist or by nobody at all. Regular audits and automated checks catch this before it causes stalled reviews or unfixed security issues.

open as a page