At twenty repositories, a person knows them all. At two hundred, somebody has a list. At two thousand, nobody knows what exists.
The transition is not gradual — there is a point at which every question about the estate becomes a research project, and past it, an organisation that has not built the tooling is operating blind.
The short answer
Section titled “The short answer”Fleet management is four capabilities, in order of dependency.
Inventory. What exists, refreshed continuously, stored historically.
Classification. What each repository is — its tier, owner, classification and lifecycle state. Metadata, not folder structure.
Standards. What every repository in a class should have, and the mechanism that applies it.
Drift detection. Where reality differs from the standard, reported to somebody who will act.
Each depends on the one before it. Standards without classification apply to everything or nothing; drift detection without standards has nothing to compare against.
When a fleet becomes a fleet
Section titled “When a fleet becomes a fleet”The threshold is not a repository count — it is a set of symptoms, and recognising them is what tells you the transition has happened.
Nobody can name the repositories. The list, when produced, contains ones that surprise people.
“Who owns this?” takes more than a minute. And frequently ends with a guess.
A security question requires asking teams. “Which repositories use this library” answered by a message to a channel rather than a query.
New repositories appear without anybody noticing. Creation is self-service and unobserved.
The same problem recurs in different repositories because there is no mechanism to fix it once.
Changes take a campaign. Anything that must apply everywhere requires a project.
Reviews are sampled rather than complete, because complete is not feasible by hand.
Two or three of these are normal at any size. All of them together means the estate has outgrown manual management, and the tooling described here is no longer optional — it is the difference between an estate you operate and one you observe.
The count where this typically happens is lower than people expect — frequently a few hundred rather than a few thousand, because the constraint is human attention rather than any technical limit.
Inventory
Section titled “Inventory”Not a spreadsheet. A generated dataset, refreshed on a schedule, with history.
What to collect per repository: name, organisation, visibility, size, default branch, creation date, last push, archived status, topics, custom properties, teams and permissions, collaborators, applied rulesets, deploy keys, app installations, branch protection, and whether it has the standard files.
Refresh it at least weekly, and keep every snapshot. The historical series is what answers “when did this change” and it costs almost nothing to store.
Include the derived fields. Age, days since last push, growth rate, whether metadata is complete. Deriving them once, in the collector, means every report uses the same definitions.
Report the collection’s own completeness. A snapshot that covered 3,200 of 3,800 repositories because a rate limit interrupted it is a snapshot that will produce wrong answers. See API automation.
The inventory is the foundation. Nothing else in this article is possible without it, and building it is a week of work that pays back permanently.
Classification
Section titled “Classification”The metadata that makes fleet operations possible, covered in detail in custom properties.
Classification is what turns a list into a population. Without it, every fleet operation applies to everything or to a hand-maintained list. With it, operations select by intent: all production repositories, all repositories handling personal data, all repositories owned by a team that no longer exists.
And it is what makes reports scoped. “Forty repositories are approaching the size limit” is a statistic. “Four production-tier repositories are approaching the size limit” is a work item with an owner.
The minimum useful set: owning team, tier, data classification, lifecycle state.
Set at creation, required, and audited for completeness.
The unclassified count is the key fleet metric. Every repository with no tier is invisible to every targeted policy, absent from every scoped report, and outside every control that selects by property. That number should be small and shrinking, and if nobody is watching it, it is neither.
Derive where you can. Ownership from a service catalogue, tier from deployment configuration. Derived values do not decay.
The shape of a large estate
Section titled “The shape of a large estate”Before designing anything, it helps to know what a fleet actually looks like, because the distribution is consistent across organisations and it is not what people expect.
A long tail dominates. A small number of repositories account for most of the activity, and most repositories have almost none. In a fleet of two thousand, perhaps two hundred see weekly commits.
A large fraction are effectively dead. No commits in a year, no open pull requests, no dependents. Frequently a third or more, and the number surprises everybody the first time it is measured.
Ownership is concentrated and stale. A minority of teams own a majority of repositories, and a meaningful fraction of ownership records name teams that no longer exist.
A few repositories are enormous. The size distribution is heavily skewed, and the top five are usually an order of magnitude larger than the median. See repository health.
Standards compliance clusters. Repositories created since the template existed comply; older ones do not. The compliance rate is largely a function of creation date rather than of team diligence.
Which shapes the strategy. Effort spent on the active minority has disproportionate impact. Effort spent chasing compliance in the dead tail is wasted — those repositories should be archived, not fixed.
And it explains why creation governance matters most. If compliance correlates with creation date, then fixing creation fixes the future permanently, while remediation only ever addresses the past.
Standards
Section titled “Standards”What a repository in a given class should have. Made concrete rather than aspirational.
Structural standards: a README with specific sections, a CODEOWNERS, a licence, a .gitignore, a security policy, a CONTRIBUTING where contributions are expected.
Configuration standards: branch protection or a ruleset, required checks, automatic branch deletion on merge, Actions permissions.
Metadata standards: the required custom properties, a description, topics.
Pipeline standards: the shared workflows called, the security scans present.
Express standards by class, not universally. A production service and a documentation repository have different reasonable requirements, and a single standard applied to both is either too strict for one or too weak for the other.
And distinguish enforced from expected. Some standards are enforced by rulesets and cannot be violated; others are expectations that drift detection reports. Both are legitimate; conflating them means nobody knows which is which.
Where standards are actually applied
Section titled “Where standards are actually applied”A standard is a statement; the mechanism that realises it determines whether it holds.
At creation, via a template. The cheapest and most durable. A repository created from a template arrives compliant, and nobody had to do anything. See repository templates.
Centrally, via rulesets and organisation settings. Applies to everything matching the targeting, including repositories that already exist and repositories created tomorrow. The strongest mechanism where the standard can be expressed this way.
Centrally, via shared workflows. Pipeline standards that every caller inherits. See standardised CI/CD.
By campaign, via bulk pull requests. For files that must exist in the repository. Expensive, and the mechanism of last resort.
By report, via drift detection. For expectations that are not enforced. Cheapest to introduce and weakest in effect.
The design question for every standard is which of these applies, and the answer determines how much it costs to maintain. A standard realised at creation and enforced centrally costs nothing ongoing. One realised by campaign costs a campaign every time it changes.
Prefer the mechanisms in the order above. Where a standard can only be realised by campaign and report, that is worth noticing — it may be a sign that the standard is asking for something that should live centrally instead.
Drift detection
Section titled “Drift detection”Compare each repository against its class’s standard, and report the differences.
Report, do not silently correct. A repository that diverges may have a reason. Overwriting it destroys the reason and the evidence that somebody made a decision.
Route reports to owners. A central list of two thousand deviations is a backlog nobody owns. A message to a team about their four repositories is actionable.
Rank by consequence. A missing licence file and an absent required review are both deviations; only one matters. A drift report that treats them equally will be ignored.
Track the trend. The absolute deviation count is less interesting than whether it is rising or falling, and the trend is what tells you whether the standards are being adopted or resisted.
And use it to test the standards. A standard that 80% of repositories deviate from is not a standard — it is an aspiration nobody agreed to, and the right response is to change it rather than to chase compliance.
Applying a change across the fleet
Section titled “Applying a change across the fleet”The operation that defines fleet management, and the one with the most ways to go wrong.
Prefer central mechanisms over per-repository changes. A ruleset, an organisation setting, a shared workflow, a required check — each is one change that reaches everything. A pull request to four hundred repositories is four hundred reviews.
Which reframes the question: before designing a fleet-wide campaign, ask whether the thing being standardised could live centrally instead. Frequently it can, and frequently nobody asked.
When a per-repository change is genuinely required — a file that must exist in the repository, a configuration the platform cannot express centrally — then it is a campaign, and it needs the discipline in API automation: dry-run, bounded, resumable, per-item logging.
Batch by team. One pull request covering a team’s eight repositories, not eight separate ones.
Give it a deadline and a stated consequence, agreed in advance.
Expect a long tail. The last 10% will be repositories that are archived, broken, unowned or unusual, and they will take as long as the first 90%. Budget for it, and be willing to declare the tail out of scope with a documented reason.
Measure adoption, not completion. How many repositories now have the thing, as a proportion of the population — including the ones you could not change.
Fleet metrics worth tracking
Section titled “Fleet metrics worth tracking”Numbers that describe the estate’s health, tracked over time rather than as snapshots.
Total repositories, and new repositories per month. The growth rate determines whether everything else is keeping up.
Unclassified and unowned counts. The governance gap.
Repositories created through the governed path, as a proportion of all new repositories. The measure of whether creation governance works.
Standards compliance by class. Should rise; a plateau means adoption has stalled.
Repositories over health thresholds. Size, branches, largest object.
Stale repositories. No activity, feeding lifecycle.
Archived per month. The counterweight to growth — an estate where nothing is ever archived only grows.
Open security alerts on unowned repositories. The number that converts fleet hygiene from tidiness into risk.
Publish the trends, not the values. A single number is an opinion; a twelve-month line is an argument.
The reports that matter
Section titled “The reports that matter”Six reports, each answering a question somebody actually asks.
The unowned and unclassified report. The governance gap. Should trend to zero.
The health report. Repositories approaching size, branch or object limits. See repository health.
The staleness report. No commits, no pull requests, open alerts. Feeds lifecycle.
The standards deviation report, by owner, ranked by consequence.
The growth report. New repositories per month, and whether they arrived through the governed path.
The access anomaly report. Direct individual grants, old outside collaborators, admin permissions. See access reviews.
Publish them on a fixed cadence, to named recipients. A report with no recipient is data; a report with a recipient who is expected to act is a process.
Who does this, and how it is funded
Section titled “Who does this, and how it is funded”A capability nobody owns is a capability that does not exist, and fleet management is unusually easy to leave unowned because no single team feels the pain.
It belongs to a platform or developer experience function, alongside the CI platform and the repository creation path. Those are the same audience and the same tooling.
It is not a security function, although security is a major consumer of its output. A fleet management capability owned by security tends to produce controls without the corresponding developer-facing improvements, and adoption suffers.
One to three people can run it for a large estate, once the automation exists. The build is a quarter; the operation is a fraction of a person.
Fund it on the risk case, not the tidiness case. “We have 340 repositories with live credentials, no owner and unaddressed security alerts” gets attention. “The repository list is messy” does not. The numbers for the first framing come out of the inventory, which is the first thing to build.
And demonstrate it with a delivery, not a report. The first output should be something teams want — a working repository creation path, a shared workflow that saves everybody effort — rather than a compliance dashboard. A fleet function that is only ever the source of deviation notices will not be welcome, and its reports will be ignored.
What legibility buys
Section titled “What legibility buys”The argument for the whole capability, stated in terms of questions that become answerable.
“Which repositories are affected by this vulnerability?” A dependency question answered from the inventory rather than by asking forty teams.
“Who owns this?” Asked constantly, and unanswerable in most large estates.
“What did we ship from this repository, and who approved it?” Combines inventory with audit data.
“Which repositories handle customer data?” A classification question, and the one that arrives with a regulatory deadline attached.
“Are we exposed to this compromised action?” A fleet search across workflow files, answered in minutes rather than days. See Actions governance.
“What would we lose if this team left?” Ownership plus activity data.
“How much of our estate is unmaintained?” The staleness report, and the honest answer is usually uncomfortable.
Each of these is asked under time pressure, and each is either a query or a project depending on whether the fleet capability exists. That difference — measured in days per question, several times a year — is what the capability actually buys.
Common mistakes
Section titled “Common mistakes”A spreadsheet inventory. Stale on the day it is written.
No historical snapshots. Retrospective questions become unanswerable.
Universal standards. Too strict for some, too weak for others.
Silent correction of drift. Destroys the reason somebody diverged.
Central deviation backlogs. Nobody owns them.
Not ranking by consequence. The report gets ignored.
Ignoring the unclassified count. It is the metric that determines every other report’s coverage.
Chasing compliance with a standard nobody agreed to. Change the standard.
Building standards before classification. They apply to everything or nothing.
Building it, in order
Section titled “Building it, in order”A sequence that produces something useful at every stage rather than after six months.
-
Write the inventory collector. Enumerate repositories with their basic attributes. A day’s work, and it immediately answers questions nobody could answer before.
-
Store snapshots. Timestamped, in object storage. The historical series starts accumulating from now, which is the argument for doing it early.
-
Publish the first report: unowned and unclassified. Uncomfortable, useful, and it makes the case for the next step.
-
Establish the classification schema and backfill by derivation where possible. See custom properties.
-
Build the governed creation path so new repositories arrive classified. This stops the problem growing while you address the existing estate.
-
Define standards for one class. Not all of them. Prove the model on the class where it matters most.
-
Add drift detection for that class, reported to owners.
-
Then widen — more classes, more standards, more reports.
-
Add the health and staleness reports once the classification is reliable enough for them to be scoped.
Steps 1 to 3 take a week and change the conversation, because they replace assertions about the estate with numbers. Everything after that is easier to fund.
Do not attempt to classify everything before building anything. A perfect schema applied to nothing is worth less than a rough one applied to the estate.
Keeping it accurate
Section titled “Keeping it accurate”An inventory that is trusted gets used; one that is occasionally wrong gets checked by hand, which defeats the purpose.
Collect from the API, never from a maintained list. Any human-maintained register is wrong within a month.
Include everything, including archived and forked repositories, and let reports filter. A collector that excludes categories produces reports whose scope nobody remembers.
Record the collection time and coverage. A report should be able to say “as of this timestamp, covering this many repositories”.
Alert when a collection fails or is incomplete. Silent partial collection produces confidently wrong reports, which is worse than no report.
Reconcile against a second source occasionally. The organisation’s own repository count, or a different query path. Discrepancies indicate a bug in the collector, and they are worth finding before somebody else does.
Version the collector’s schema. As you add fields, older snapshots lack them, and reports spanning the change need to handle that rather than silently producing gaps.
And publish what it does not cover. Repositories in organisations the app is not installed on, personal repositories, and anything outside the enterprise are all invisible. Stating the boundary is what makes the data trustworthy.
Integrating with the wider estate
Section titled “Integrating with the wider estate”GitHub is one system, and fleet data is most valuable when it connects to the others.
The service catalogue is usually the authoritative record of what runs in production. Repositories should link to catalogue entries and vice versa, and the link is what lets an incident responder go from a failing service to its code in one step.
The identity directory owns team membership. Repository ownership metadata should reference teams that exist there, and reconciliation between the two is what keeps ownership honest. See team synchronisation.
The vulnerability management system needs to know which repositories are in scope for which policy, which is a classification question.
The CMDB or asset register, where one exists, may consider repositories assets. Feeding fleet inventory into it is usually easier than maintaining a parallel record.
The on-call system knows who is responsible right now, which is frequently more current than any static ownership record.
Pick one source of truth per fact, and derive the rest. Ownership recorded in three systems will disagree within a quarter, and the disagreement is worse than any single wrong answer because nobody knows which to believe.
Derive into GitHub rather than maintaining in it, where an external system is authoritative. A custom property populated nightly from the service catalogue is always correct; one maintained by hand is correct on the day it was set.
Mental model
Section titled “Mental model”A fleet is a population with a distribution, not a list. Managing it means knowing what is in it, what each member is, what each should look like, and where reality differs — and then routing that difference to somebody who can act. Every one of those steps depends on classification, which is why metadata is the foundation rather than a detail.
What you learned
Section titled “What you learned”- Fleet management is inventory, classification, standards and drift detection, in that dependency order
- Inventory should be generated, scheduled, historical, and report its own completeness
- Classification by custom property is what makes every targeted policy and scoped report possible
- The unclassified repository count is the metric that bounds every other report’s coverage
- Standards should vary by class and distinguish enforced from expected
- Drift should be reported to owners, ranked by consequence, never silently corrected
- A standard most repositories deviate from is not a standard
- Six reports cover the questions that recur; each needs a named recipient
- Historical snapshots answer retrospective questions that current state cannot
Exercise
Section titled “Exercise”Use an organisation you administer.
-
Produce a full repository inventory with visibility, size, last push and custom properties.
-
Count repositories with no owning team recorded. Predict: what fraction?
-
Define a standard for one class of repository. List five concrete requirements.
-
Measure deviation from that standard across the class. Predict: what percentage comply?
-
If compliance is below half, decide whether to change the standard or drive adoption. Justify.
-
Rank the deviations by consequence. Which three actually matter?
-
Identify who would receive each of the six reports.
-
Estimate the work to automate the inventory and one report.