Skip to content
Dev Tools Article

The Repository Ownership Gap: How GitHub Solved Its Own Metadata Sprawl

Why CODEOWNERS and service catalogs aren't enough to secure and manage thousands of repositories at enterprise scale.

Lenn Voss
Lenn Voss
Cloud & Infrastructure Writer · Jul 9, 2026 · 6 min read
The Repository Ownership Gap: How GitHub Solved Its Own Metadata Sprawl

In any sufficiently large engineering organization, repository creation is cheap, but repository cleanup is virtually non-existent. Over time, this asymmetry breeds a quiet crisis of unowned code.

GitHub itself ran into this exact wall. Within its primary internal organization, the company had over 14,000 repositories. By early 2025, more than 11,000 of these were active and unarchived, but the vast majority lacked any clear, recorded owner. While repositories tied directly to production services were well-documented, thousands of others—internal tools, documentation hubs, one-off scripts, and personal sandboxes—drifted in administrative limbo.

This metadata gap isn't just an organizational annoyance. It is a security risk. When an automated secret scanner flags a leaked credential in a random repository, security teams must act. If they rotate the secret blindly, they risk breaking an undocumented dependency. If they wait to find the owner, the exposure window widens. Finding that owner manually means digging through git commit histories, reading outdated READMEs, or asking around in Slack.

To solve this, GitHub built a system to enforce durable, programmatic repository ownership. Their approach offers a highly practical blueprint for any enterprise struggling with repository sprawl.

The Limits of Service Catalogs and CODEOWNERS

Most engineering teams attempt to solve ownership using one of two existing patterns, both of which fall short at scale.

First, there is the Service Catalog. Platforms like Spotify Backstage or GitHub's own internal catalog map deployed services to their respective repositories. This works well for production infrastructure, but it relies on a many-to-one relationship: a service maps to a single repository, but a single repository can house multiple services. Reverse-looking up an owner starting from a repository only works if that repository is explicitly registered in the catalog. It completely misses non-service repositories.

Second, there is the CODEOWNERS file. While excellent for routing pull request reviews to specific teams or individuals, it is file-centric rather than repository-centric. Querying CODEOWNERS globally across thousands of repositories requires cloning every repository or heavily querying the GitHub API, making it a poor fit for organization-wide compliance and inventory management. Furthermore, because it is stored in-repo, it is easily bypassed or left to rot.

To establish true ownership, metadata must live outside the repository's codebase but remain tightly coupled to the repository asset itself.

The Custom Properties Blueprint

Instead of maintaining a centralized, external registry or forcing developers to commit a metadata.yaml file to every repository, GitHub utilized its own Custom Properties feature. This approach keeps metadata native, structured, and queryable at the organization level via the API.

They defined a simple schema using two custom properties:

  1. ownership-type: An enum accepting three values: Service Catalog, Hubber Handle (individual employee), or Team.
  2. ownership-name: A text field containing the identifier of the owner.

This schema covers the entire lifecycle of code. A repository is either a production service (backed by an on-call rotation), a shared team asset (like documentation or internal tooling), or a personal experiment.

Crucially, the system does not rely on manual data entry alone. A dedicated validation engine checks the inputs against live systems:

  • Individual handles are validated against active organization membership.
  • Teams must exist in the organization and have at least two members. This aligns with industry best practices, such as Google's open-source policies and GitHub's own continuity guidelines, which recommend having at least two owners to prevent administrative lockouts when employees depart.
  • Service Catalog entries are verified against the live catalog database.

Designing the Enforcement Loop

To transition thousands of legacy repositories to this new model, GitHub built an automated enforcement loop using a GitHub App backed by a Kubernetes CronJob.

Because the enforcement logic requires access to internal systems, the Service Catalog, and the GitHub API, running it inside a standard GitHub Actions workflow was impractical. Instead, the external cron job orchestrates the state machine of repository compliance:

flowchart TD
    A[Scan Repositories] --> B{Has Owner Property?}
    B -- Yes --> C[Do Nothing]
    B -- No --> D[Create Warning Issue]
    D --> E{Owner Added within 30 Days?}
    E -- Yes --> F[Auto-close Issue]
    E -- No --> G[Archive Repository]

When the scanner detects an unowned repository, it opens a warning issue within that repository. If the owner properties are populated within a 30-day grace period, the app automatically closes the issue. If the deadline passes without action, the system archives the repository.

Archiving is the ideal enforcement mechanism. Unlike deletion, it is non-destructive and fully reversible, but it immediately stops active development and signals to the organization that the repository has been abandoned. During their rollout, GitHub successfully archived roughly 8,000 inactive repositories using this method, instantly shrinking their attack surface.

One operational detail is worth noting: scheduling matters. GitHub ran their initial enforcement cron job on a Saturday morning, assuming low activity would minimize disruption. Instead, because software engineering is globally distributed, automated issues began popping up immediately, causing confusion on Slack. For platform teams implementing similar guardrails, communication and scheduling during core business hours are critical to avoiding unnecessary friction.

Implementing Programmatic Guardrails

Cleaning up legacy repositories is only half the battle. To prevent metadata decay from returning, ownership must be enforced at the point of creation.

By integrating these custom properties into repository creation workflows, organizations can block the creation of any new repository that does not have valid ownership-type and ownership-name values defined.

While this introduces a minor point of friction for developers, the trade-off is highly favorable. The alternative is a return to manual forensic work every time a security alert is triggered. By treating repository metadata as a first-class, validated property, engineering organizations can maintain a clean, self-documenting inventory that scales naturally with their codebase.

Sources & further reading

  1. How GitHub gave every repository a durable owner — github.blog
  2. GitHub Organization Owners | Google Open Source — opensource.google
  3. Maintaining ownership continuity for your organization - GitHub Docs — docs.github.com
  4. forking - GitHub repository ownership when working for a company - Open Source Stack Exchange — opensource.stackexchange.com
  5. How to know who is the maintainer of a GitHub repository? - Stack Overflow — stackoverflow.com
Lenn Voss
Written by
Lenn Voss · Cloud & Infrastructure Writer

Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.

Discussion 0

Join the discussion

Sign in or create an account to comment and vote.

No comments yet

Be the first to weigh in.

Related Reading