skip to content

A polyrepo gets natural access control for free -- GitHub/GitLab repo-level permissions restrict who can see or push to a given project. How do organizations enforce equivalent access control inside a single monorepo, and what are the limits of that approach?

level: seniorimportance: should knowfreq 40%

answer

  1. repo ACL vs path-scoped CODEOWNERS gate
  2. review gate != hard technical barrier
  3. Piper's true per-directory read ACLs as the rare/expensive case
  4. sensitive material often lives outside the monorepo entirely

basics

~20 s

Since everything is in one repo, you can't just lock a whole repo per team. Instead, tools restrict access by folder -- who can approve merges where -- using code-review rules, and for real secrets, keeping them in a separate system entirely.

solid answer

~50 s

Monorepos replace repo-level ACLs with path-based mechanisms: CODEOWNERS-style files that require the right team's approval before a given directory can be merged into, branch-protection rules keyed on path, and in the most sophisticated setups (Google's Piper), genuine read ACLs on specific subtrees so even grep-level visibility is restricted per directory, not just write access. The limits are real: path-based write control (CODEOWNERS) is a review gate, not a hard technical barrier -- a determined or careless engineer with general repo write access can often still push if the gate is misconfigured or bypassed, whereas a polyrepo's access control is enforced by the hosting platform's ACL, independent of any one file. True read-restriction inside a monorepo is expensive engineering (most hosted Git platforms don't support per-directory read ACLs at all), so the common compromise is 'restrict genuinely sensitive material (secrets, crypto keys) to a separate system entirely' rather than trying to wall it off within the shared tree, accepting that most monorepo code is readable org-wide by design.

go deeper

for a junior

Should recognize that a monorepo can't just lock the whole repo per team the way separate repos can, and that some path-based file (like a CODEOWNERS convention) is commonly used to route review.

for a middle

Should distinguish a review-gate mechanism (CODEOWNERS + branch protection) from a hard access-control mechanism, and know it mainly governs merge approval, not raw read/write access.

for a senior

Should articulate the read-vs-write distinction clearly, know that true per-directory read ACLs are rare/expensive (citing something like Piper), and know the common practical workaround (move sensitive code to its own repo or a secrets system).

for a principal

Should be able to advise, given a specific compliance/confidentiality requirement, whether it's cheaper to build monorepo-grade path ACLs or simply carve that one concern out into a separately-ACL'd repository -- an organizational and cost trade-off, not just a technical one.

## The baseline: a repository-level ACL A **repository-level ACL** is the access-control mechanism nearly every hosted Git platform (GitHub, GitLab, Bitbucket) gives you by default: you invite a team to a repository with read or write permission, and that permission applies uniformly to the entire repository. In a polyrepo, this is enough -- because each project already lives in its own repository, restricting who can read or push to 'the payments service' is just restricting who can access 'the payments-service repo.' The repo boundary and the access boundary are the same boundary, so no extra mechanism is needed. ## Why a monorepo breaks that equivalence A monorepo breaks that equivalence on purpose -- the whole point is that many projects share one repository -- so 'restrict access to just this one team's code' can no longer be expressed as 'restrict access to this repository.' Organizations rebuild the equivalent protection at a finer grain, and they do it in layers that trade off enforcement strength against implementation cost. ## The cheapest layer: review-gated path ownership The cheapest and most common layer is write-side, review-gated: a `CODEOWNERS` file maps directory paths to the team or individuals who must approve a pull request touching that path, and branch-protection rules make that approval mandatory before merge. This is genuinely useful -- it stops accidental or unreviewed changes to another team's code -- but it's a process control enforced at merge time, not a technical barrier on read or direct write access; anyone with general write access to the repository can typically still push a branch, open a PR, or in a misconfigured setup even merge without the required approval if branch protection has a gap. A common real incident pattern is: - an admin override - a bot with elevated permissions - a newly-added path with no owners file yet ## A stronger layer: path-scoped write restriction A stronger, more expensive layer is genuine **path-scoped write restriction** at the Git-hosting or pre-receive-hook level -- rejecting the push itself, server-side, if the pusher isn't authorized for the paths touched, rather than relying on a PR-review gate that a determined actor could route around. Some large-scale custom systems implement this; most off-the-shelf hosted Git platforms do not offer true per-directory push ACLs, which is a real practical limitation teams hit when they try to replicate polyrepo-grade access control inside GitHub/GitLab monorepos. ## The strongest and rarest layer: read-side restriction The strongest and rarest layer is **read-side restriction**: preventing engineers who aren't on a given team from even seeing that team's directory, not just from writing to it. This matters because a monorepo's core selling point -- anyone can grep anything -- is in direct tension with any team that has genuinely sensitive code: - crypto key material - an unreleased product - an acquisition-related codebase - region-specific compliance code that must not be visible outside a jurisdiction Google's Piper is the best-known system that actually implements fine-grained read ACLs on subtrees of the monorepo, so specific directories are invisible to engineers without explicit grant -- but this required building a custom version-control backend from scratch; it isn't a feature you get by adopting Git plus a convention file. ## What underinvesting here looks like The practical failure mode when organizations underinvest here is predictable. Teams either accept that most of the monorepo is readable by everyone (which is the common, deliberate choice for genuinely non-sensitive code, matching the monorepo's discoverability goal) or, when something really must be restricted, pull it out of the shared monorepo into its own separately-ACL'd repository or an entirely separate secrets-management system (a dedicated secrets vault or a standalone repo) -- implicitly conceding that the monorepo's access model can't cover that case. Trying to force genuine confidentiality guarantees onto a CODEOWNERS-only setup is a classic anti-pattern: a security review will note that `CODEOWNERS` prevents accidental unreviewed merges but does not prevent someone with baseline repo access from reading the sensitive path or force-pushing around the review gate, so treating it as a hard security boundary rather than a review-convenience feature is a common, exploitable misunderstanding. ## The upshot for weighing the two models The upshot for weighing monorepo vs. polyrepo on this axis specifically: - If an organization has hard compliance or confidentiality requirements that map cleanly onto team boundaries -- a regulated subsidiary's code, export-controlled material, pre-acquisition due-diligence code -- a polyrepo's free repo-level ACL is a much cheaper way to get a real boundary than building or buying monorepo-grade path ACLs. - Conversely, if 'access control' mostly means 'don't let people carelessly break other teams' code without review,' CODEOWNERS-style path ownership inside a monorepo is usually sufficient and far cheaper than splitting repos.

  • Why isn't a CODEOWNERS-style approval requirement considered a real security boundary?
    Because it's enforced at merge/review time by the hosting platform's branch-protection configuration, not by preventing the underlying read or write action itself -- anyone with general repository access can typically still push a branch or open a PR, and misconfiguration, admin overrides, or automation with elevated tokens can bypass the required-approval gate entirely. A real security boundary needs to reject the unauthorized action server-side regardless of process, which is what true path-scoped ACLs (or a separate repository) provide and CODEOWNERS alone does not.
  • If a company has one subtree in its monorepo containing export-controlled or regulatory-sensitive code, what's the pragmatic fix given that most Git hosts don't support per-directory read ACLs?
    Pull that subtree out into its own separately-hosted repository with its own repo-level ACL, since that's the access-control granularity most hosting platforms actually enforce well. This sacrifices some of the monorepo's cross-project discoverability for that one subtree, but it's usually far cheaper and more reliable than building or buying genuine fine-grained read-ACL infrastructure for a single sensitive area.

A polyrepo is like separate locked offices with separate keys -- the building's front-desk access list is the whole security model. A monorepo is more like one big open-plan office with locked filing cabinets scattered around for genuinely sensitive folders -- most desks are visible to everyone by design, and true locks are the expensive exception, not the default.

saying these in an interview costs you the question

  • thinks CODEOWNERS is a hard security boundary equivalent to a repo ACL
  • assumes every monorepo has true per-directory read restriction out of the box
  • doesn't distinguish write-side review gates from read-side visibility restriction
  • unaware that most hosted Git platforms lack native per-directory push/read ACLs

context