Skip to content
ExponaBLOG
GIT & GITHUB FOR PROFESSIONAL DEVELOPERS · DAY 036 / 100

CODEOWNERS: what every Git & GitHub developer should know

Automatic reviewers for critical code.

Expona Admin7 min read

By day 36 of your Git and GitHub journey, you've mastered branches, pull requests, and code reviews. But if you're still assigning reviewers manually on every PR, you're missing a powerful automation that scales with your team. CODEOWNERS: what every Git & GitHub developer should know isn't just about file permissions—it's about encoding team expertise directly into your repository so the right people review the right code, automatically.

Why CODEOWNERS matters in mature teams

As teams grow beyond five or six engineers, manual reviewer assignment becomes a bottleneck. You either assign random people (risking inexpert reviews) or spend time hunting down the right person for each change. CODEOWNERS solves this by mapping repository paths to teams or individuals, making GitHub automatically request reviews from the people who actually understand that code.

In a real production scenario, imagine a team with frontend engineers, backend engineers, and a small payments specialist. When someone submits a PR touching the Stripe integration, you want that specialist's eyes on it—not a random frontend engineer who last touched that code six months ago. CODEOWNERS makes that happen instantly, without anyone thinking about it.

The secondary benefit is cultural: CODEOWNERS clearly defines who owns what, which helps new team members understand the codebase structure and reduces the "who should I ask about this?" conversations in Slack.

Map paths to teams

The CODEOWNERS file lives in your repository root (or in .github/ or docs/) and uses a simple pattern matching syntax inspired by .gitignore. Each line maps a path pattern to one or more owners.

bash
# Basic syntax: <path> <owner1> <owner2> ...
# Owners can be @username, @org/team-name, or email addresses

# Frontend team owns everything in src/
src/ @myorg/frontend

# Backend team owns the API
src/api/ @myorg/backend

# Payments specialist owns payment processing
src/api/payments/ @payments-specialist

# Everyone reviews security and dependencies
*.lock @myorg/security-team
.github/ @myorg/devops

# Root config files need backend and devops sign-off
docker-compose.yml @myorg/backend @myorg/devops
.env.example @myorg/backend

GitHub matches patterns top-to-bottom, so more specific patterns should appear later in the file. In the example above, src/api/payments/ will be owned by the payments specialist even though src/api/ is owned by the backend team, because the more specific rule takes precedence.

For team names, use the GitHub organization team reference format: @org/team-slug. You can find your team slug by visiting your organization's teams page—it's the lowercase, hyphenated version of the team name. For individual usernames, use @username.

A real-world CODEOWNERS file in a mid-sized SaaS application might look like this:

bash
# Root-level infrastructure
Dockerfile @myorg/devops
docker-compose.yml @myorg/devops
.github/workflows/ @myorg/devops
terraform/ @myorg/devops

# Frontend application
src/components/ @myorg/frontend
src/pages/ @myorg/frontend
src/styles/ @myorg/frontend
public/ @myorg/frontend

# Backend API
src/api/ @myorg/backend
src/models/ @myorg/backend
src/middleware/ @myorg/backend

# Specialized domains
src/api/payments/ @payment-engineer
src/api/auth/ @auth-engineer
src/database/ @myorg/backend @database-specialist

# Dependencies and security
package.json @myorg/frontend
package-lock.json @myorg/frontend
requirements.txt @myorg/backend
requirements.lock @myorg/backend
Gemfile @myorg/backend
.github/dependabot.yml @myorg/devops

# Everything else defaults to core team
* @myorg/core

The wildcard at the end ensures a default reviewer is always requested, preventing orphaned code that nobody feels responsible for.

Required reviews for owned paths

Once CODEOWNERS is in place, GitHub automatically adds owners as reviewers when a PR touches their code. But for truly critical paths—payment processing, authentication, infrastructure—you should require approval from a code owner before merging.

This is configured in your branch protection rules, not in CODEOWNERS itself. Here's how to set it up:

  1. Go to your repository Settings → Branches
  2. Click "Add rule" under Branch protection rules
  3. Enter the branch name (usually main or master)
  4. Check "Require a pull request before merging"
  5. Check "Require approvals from Code Owners"
  6. Set the number of required approvals (usually 1, sometimes 2 for critical changes)
  7. Optionally check "Dismiss stale pull request approvals when new commits are pushed"

With this configuration, a PR touching src/api/payments/ cannot merge until the payments specialist explicitly approves it. The "Dismiss stale approvals" option ensures that if a developer pushes new commits after approval, the code owner must review again.

In practice, this creates a lightweight enforcement mechanism. Developers can't bypass critical code ownership through accident or laziness; they must wait for the right person to review. This is especially valuable in regulated environments (fintech, healthcare) or when handling sensitive data (user authentication, payment processing).

Keep it updated

CODEOWNERS is only useful if it reflects your current team structure. When engineers join or leave, when teams are reorganized, or when a specific subsystem changes ownership, update CODEOWNERS immediately.

Many teams treat CODEOWNERS updates as part of their onboarding and offboarding checklists. When a new backend engineer joins, add them to @myorg/backend in GitHub (the organization level), and they're automatically an owner for all backend paths. When a specialist leaves, move their specific domain ownership to a team or colleague.

Some teams automate this. For example, if you use a service like Snyk or Dependabot for dependency management, your security team should own dependency files. If you add new configuration systems, update CODEOWNERS before or immediately after the first merge.

A practical approach: every quarter, as part of a team sync or retrospective, spend five minutes reviewing CODEOWNERS. Is it still accurate? Have new subsystems emerged that need an owner? Have responsibilities shifted? This small maintenance cost prevents the file from becoming outdated and irrelevant.

Avoid one person owning everything

A common anti-pattern is having a single "code owner" (often a tech lead or senior engineer) assigned to vast swaths of the codebase. This creates bottlenecks and misses the point of CODEOWNERS, which is to distribute ownership based on expertise.

Instead, think about domain ownership. Payments is a domain. Authentication is a domain. Frontend state management is a domain. Within each domain, assign the people who understand it best. For shared or foundational code that multiple teams touch, assign multiple owners or a team.

Here's the anti-pattern:

bash
# Bad: Everything goes to the tech lead
src/ @tech-lead
.github/ @tech-lead
terraform/ @tech-lead
* @tech-lead

This defeats the purpose. Your tech lead becomes a review bottleneck and doesn't have the time to properly review everything. Junior engineers feel like they can't approve anything, even if they wrote the code.

Here's a better approach:

bash
# Good: Distributed ownership by domain
src/components/ @frontend-team
src/api/ @backend-team
src/api/auth/ @auth-engineer @backend-team
terraform/ @devops-team
.github/workflows/ @devops-team

# Fallback for uncategorized code
* @backend-team

With this setup, the senior engineer on the frontend team handles frontend reviews, the backend team owns the API, the devops engineer handles infrastructure. Each domain has clear ownership, reviews are distributed across expertise, and bottlenecks are eliminated.

If you have code that truly requires senior review (like a critical security module), use the required approvals setting on branch protection rather than assigning it exclusively to one person in CODEOWNERS. That way, multiple people can approve, but at least one person from that domain must review.

Common mistakes

  • Forgetting to enable required approvals: CODEOWNERS is just a recommendation without branch protection. Developers can merge without waiting for the owner's review. Always pair CODEOWNERS with "Require approvals from Code Owners" in branch protection rules.
  • Making CODEOWNERS too granular: Assigning ownership to individual files instead of directories creates maintenance overhead. Use directory patterns like src/api/ rather than src/api/user.service.ts.
  • Assigning non-existent teams or users: If you reference a team that doesn't exist or has a typo, GitHub silently fails to add reviewers. Verify team slugs are correct before committing CODEOWNERS.
  • Never reviewing the CODEOWNERS file itself: Changes to CODEOWNERS are code. Treat them with the same rigor as any other change. Have a senior engineer review CODEOWNERS modifications to catch mistakes.
  • Leaving CODEOWNERS at the root when it should be in .github/: Both locations work, but .github/CODEOWNERS is clearer about where configuration files live. Be consistent with your team's convention.
  • Ignoring stale assignments: If a developer moves teams but CODEOWNERS still lists them, reviews go to the wrong person. Make CODEOWNERS updates part of your team change process.

Key takeaways

  • CODEOWNERS maps repository paths to teams or individuals, automating reviewer assignment and encoding domain expertise into your workflow.
  • Use GitHub team references (@org/team-slug) for groups of people and individual usernames for specialists. Keep patterns broad (directories) rather than granular (files).
  • Always pair CODEOWNERS with required approvals in branch protection rules for critical paths like payments, authentication, and infrastructure.
  • Update CODEOWNERS whenever your team structure changes, and review it quarterly to catch drift.
  • Distribute ownership by domain rather than centralizing it on a single person. Multiple owners for a domain is better than a bottleneck.
  • CODEOWNERS is a lightweight mechanism for scaling code review. It reduces friction, prevents knowledge silos, and ensures the right expert eyes see critical changes.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles