Developer ToolsWeb ScrapingData IntelligenceApifyPPE Pricing

What Is Bus Factor? (And Why Most GitHub Projects Fail It)

Bus factor is the minimum contributors who'd need to leave for a project to stall. Most GitHub repos quietly fail it — here's how to spot it at scale.

Ryan Clinton

The problem: Most teams discover their dependency tree has a bus factor problem the same way — after a maintainer disappears, not before. The 30,000-star utility everyone trusts gets quietly flagged as a single-maintainer project six months ago, the maintainer burns out, releases stop, an unpatched CVE shows up two months later, and the post-mortem reads "we didn't realise it was a one-person project." The real failure isn't that the maintainer left. It's that nobody was measuring the right thing in the first place. Lifetime contributor counts hide the problem. Rolling-window concentration exposes it.

What is bus factor? Bus factor is the minimum number of contributors who would need to leave a project for it to stall. A bus factor of 1 means a single person's departure ends the project. The metric is named after the (morbid) thought experiment "what happens if the lead developer gets hit by a bus" — the same idea is published as "truck factor" or "lottery factor" in academic literature. It's a concentration signal, not a count.

Why it matters: Bus factor is a leading indicator of supply-chain failure. The Sonatype 2024 State of the Software Supply Chain report found that 2 of 3 open-source projects commercial application teams depend on have become dormant. The Synopsys 2024 OSSRA audit of 1,067 commercial codebases found 84% contained at least one open-source component with a known vulnerability. Single-maintainer dependencies are the projects that produce both outcomes — they go dormant, they don't patch, and the consumer team finds out months later.

Use it when: You're auditing a dependency tree, screening an investment, or evaluating any open-source library that will run in production where "the maintainer disappeared" is not an acceptable failure mode.

Quick answer:

  • What it is: A concentration signal — the minimum contributors whose departure would stall the project, computed from rolling-window commit share, not lifetime totals.
  • When to use it: Any adoption decision, any dependency audit, any technical due diligence on an open-source project.
  • When NOT to use it: First-party internal repos with full context, or throwaway prototypes where dependency risk is irrelevant.
  • Typical steps: Compute top-contributor share over a rolling window, weigh it against project criticality, output a risk verdict.
  • Main tradeoff: A clean bus-factor read needs contributor enrichment data — more API calls than raw search, in exchange for a signal you can actually act on.

If you only remember 5 things:

  1. Bus factor is concentration, not headcount. A repo with 547 lifetime contributors but where one person did 92% of the last 12 months of commits has a bus factor of 1.
  2. Lifetime totals lie. The number of people who ever contributed is irrelevant. The number actively shipping in the last 90-365 days is what matters.
  3. Bus factor 1 isn't always bad. A small focused utility with one author and a clear scope is fine. A high-criticality production dependency with one author is a problem.
  4. The right signal pairs concentration with impact. topContributorShare > 0.8 only matters if the project is critical. ifMaintainerLeaves: PROJECT_LIKELY_STALLS adds the impact half.
  5. Measure across a fleet, not one repo at a time. Eyeballing a single contributor graph is fine. Auditing 200 dependencies needs an actor.

Problems this solves:

  • How to identify single-maintainer dependencies in my dependency tree
  • How to measure bus factor across hundreds of repos at once
  • How to predict what happens if a project's top maintainer disappears
  • How to distinguish a fragile single-maintainer repo from a healthy distributed one
  • How to flag bus-factor risk during open-source due diligence
  • How to scan a tech category for repos that pass popularity tests but fail concentration tests

Examples table — what bus factor actually looks like:

Repo profileLifetime contributorsTop contributor share (last 365d)Real bus factorRisk read
30k-star utility, 547 lifetime contributors, one author shipping 92% of last year's commits5470.921HIGH bus factor risk, PROJECT_LIKELY_STALLS
3k-star niche library, 18 active contributors, top share 23%840.234-6LOW bus factor risk, distributed
12k-star framework, foundation-governed, top share 89% (paid lead maintainer)3120.891 by share, but governance-strongMODERATE — share alone overstates risk
Small focused tool, 1 author, clear scope, stable for 4 years41.001Acceptable for scope; risky as a production dep
8k-star library, top share 47%, second contributor 31%, third 12%920.472-3LOW-MEDIUM bus factor risk

The takeaway: lifetime contributor count tells you almost nothing. Rolling-window concentration plus context is what flags real risk.

What is bus factor in software?

Definition (short version): Bus factor is the minimum number of project contributors who would need to suddenly become unavailable for the project to stall — measured by recent-commit concentration, not by lifetime contributor total. A bus factor of 1 means the project depends on a single person.

The metaphor is morbid on purpose. "What happens to this project if the lead developer is hit by a bus?" is the original framing — published in the agile and open-source community in the early 2000s. Academic work on the same concept calls it "truck factor" (the Avelino et al. 2016 study of 133 popular GitHub projects formalised this) or "lottery factor" (same idea, friendlier framing). All three names refer to the same metric: a count of how many critical contributors a project has, where "critical" is operationally defined as authoring a meaningful share of the codebase.

There are roughly four ways the term gets used in practice:

  1. Naive bus factor — "How many lifetime contributors are listed on the GitHub page?" This is the version that's wrong. It's a popularity stat, not a risk stat.
  2. Active bus factor — "How many contributors made meaningful commits in the last N months?" Closer to right, still incomplete.
  3. Concentration-weighted bus factor — "What's the minimum number of contributors whose combined commit share crosses some threshold (typically 50% or 80%) of recent activity?" The version academic papers use.
  4. Impact-weighted bus factor — Concentration + criticality. A small utility with one author is bus factor 1 but low impact. A core auth library with one author is bus factor 1 and catastrophic impact. Same number, different risk.

Also known as: truck factor, lottery factor, hit-by-a-bus number, key-contributor concentration, single-maintainer risk, contributor concentration index, project resilience factor.

JSON output example — bus-factor fields

Here's what a bus-factor read looks like for a fragile repo flagged by an audit:

{
    "fullName": "example-org/popular-utility",
    "stars": 30420,
    "contributors": {
        "count": 547,
        "topContributorShare": 0.92,
        "signedCommitRatio": 0.41
    },
    "activityStats": {
        "commitActivity90d": 14,
        "commitActivity365d": 68,
        "weeklyCommitAvg90d": 1.1
    },
    "maintenance": {
        "status": "AT_RISK",
        "trajectory": "DECLINING",
        "busFactorRisk": "HIGH",
        "ifMaintainerLeaves": "PROJECT_LIKELY_STALLS",
        "confidence": "HIGH"
    },
    "forecast": {
        "abandonmentRisk90d": "MEDIUM",
        "confidence": "HIGH"
    }
}

Read in order: 547 lifetime contributors looks reassuring; topContributorShare: 0.92 flips it. Weekly activity dropped to ~1 commit a week. Bus factor risk reads HIGH. The ifMaintainerLeaves field projects PROJECT_LIKELY_STALLS — meaning if the dominant maintainer steps away, the structure isn't there to absorb it. Same repo, but one signal — count: 547 — would have produced the wrong verdict.

Why most measurements get bus factor wrong

The popular framing — "how many contributors does this repo have?" — is the wrong question. The right one is "how concentrated is recent activity in one or two people?" These two questions look similar; they produce wildly different verdicts.

Lifetime totals don't decay. GitHub's contributor badge counts everyone who ever pushed — the person who fixed a typo in 2018, the bot that auto-bumps dependencies, the drive-by PR author whose one merged change is six years old. A repo with 547 lifetime contributors and one person doing all current work is a 1-contributor project with 546 historical artefacts. Same problem applies to lifetime commit count: 5,000 commits with 92% from one author looks identical, in raw count terms, to 5,000 commits distributed across 30 people. Lifetime totals erase the distinction the audit needs.

Rolling-window concentration is the right signal. What share of commits in the last 90 or 365 days came from the top contributor? That number changes when the top maintainer slows down, when a new contributor takes over, when governance shifts. It reflects current state. The actor's contributors.topContributorShare field computes this directly; commitActivity90d and commitActivity365d frame the time window so the share isn't a stale snapshot.

Naive measurement vs intelligence-layer measurement

Three different ways teams try to measure bus factor — with the failure mode each one has:

ApproachWhat it measuresFailure modeCatches single-maintainer 30k-star repo?
Lifetime contributor countCumulative people who ever pushedBots, drive-by PRs, and ex-contributors all countNo — would read 547 contributors as healthy
Recent contributor count (last 90d)Distinct authors in a recent windowCounts a one-typo PR as equal to a 90% maintainerNo — would read 8 recent contributors as healthy
Rolling-window concentrationTop contributor's share of commits over 90d/365dNeeds additional context for criticalityYes — topContributorShare: 0.92 flags it directly
Impact-weighted bus factorConcentration plus project criticality and governanceMost expensive to computeYes — combines topContributorShare with ifMaintainerLeaves impact

Approach quality based on internal testing patterns observed in April–May 2026 when scanning popular GitHub categories. Specific failure rates depend on category and team baseline.

The honest summary: lifetime counts answer the wrong question. Recent-window counts answer the right question with low signal. Rolling-window concentration answers the right question. Impact-weighted concentration answers the right question and lets you act on the answer.

If you scan any popular GitHub category — utility libraries, CLI tools, framework plugins, dev-tool wrappers — you'll find that a non-trivial fraction of the repos with high stars look reassuring on the contributor count and fail spectacularly on rolling-window concentration. This isn't a moral failure of the maintainers. It's the structural reality of open-source.

Most projects are passion projects. Someone built a thing in their spare time, it caught on, the community started depending on it, and the original author stayed in the driver's seat — because the project was their idea, because no one else stepped up, or because review and onboarding co-maintainers is itself a job. The result: a popular project shipped almost entirely by its original author. That's bus factor 1 by definition.

Maintainer burnout is well-documented. Eghbal's 2020 book Working in Public and the broader open-source maintainer burnout literature trace the same pattern: a single maintainer carries an outsized share of a popular project, the work scales faster than they can hire help, and eventually they slow down or step away. The downstream consumers — the teams who depend on the project — usually don't see it coming.

The xz-utils incident (CVE-2024-3094) is the canonical cautionary tale. In March 2024, Andres Freund publicly disclosed a backdoor planted in liblzma (part of the xz-utils project) that affected the SSH daemon on most Linux distributions. The technical details are widely covered; the bus-factor angle is the part most relevant here. The project had been maintained for years by a single person — Lasse Collin — who explicitly described the burnout pattern in public correspondence. A new contributor, "Jia Tan", spent roughly two years building trust through legitimate-looking contributions, was added as a co-maintainer, and used that access to plant the backdoor. Single-maintainer concentration was the precondition that made the social-engineering takeover viable. A project with five active co-maintainers and a code review culture would have made the same attack significantly harder. The supply-chain risk wasn't only the malicious code — it was the structural fact that one person was the gatekeeper.

The takeaway is not "single-maintainer projects are dangerous." It's "single-maintainer projects in critical positions are the projects that need active second-source planning, not optimistic trust." Bus factor by itself is just a number; bus factor in context is risk.

Bus factor plus project criticality equals risk

Bus factor is a concentration measurement. It becomes a risk signal only when paired with project criticality — the cost of the project stalling.

Repo A:                          Repo B:
547 lifetime contributors        84 lifetime contributors
0.92 top contributor share       0.23 top contributor share
   (last 365d)                      (last 365d)
        ↓                                ↓
   bus factor 1                    bus factor 4-6
   (one person, 546 ghosts)        (genuinely distributed)

The headcount column lies. The concentration column tells the truth. That's the article in one diagram.

But concentration alone is not risk. Concentration plus criticality is risk. A bus factor of 1 on a 200-line CLI utility that wraps a single API endpoint is fine — small scope, easy fork, low criticality. A bus factor of 1 on a JSON parsing library used in production by half the Node.js ecosystem is catastrophic — thousands of downstream projects inherit the maintenance burden, the security responsibility, and the migration cost.

Same bus factor, incomparable risk. The 2×2 you actually filter on:

Low criticalityHigh criticality
Low concentrationSafe — distributed and low-stakesMonitor — distributed but high-stakes
High concentrationAcceptable — concentrated but disposableDangerous — concentrated and load-bearing

The bottom-right cell is the second-source planning list. Everything else is either fine or watch-list.

The actor models this with the ifMaintainerLeaves field, which has three values:

  • MINIMAL_IMPACT — Even with concentrated commits, the project would survive a maintainer departure: small scope, stable feature set, easy to fork, low criticality.
  • MODERATE_IMPACT — A maintainer departure would slow the project but not end it: some governance structure, secondary contributors who could ramp, recoverable in months.
  • PROJECT_LIKELY_STALLS — A maintainer departure would effectively end the project: high concentration, no governance, no obvious successor, high consumer dependency.

The combined signal you actually filter on for a dependency audit is busFactorRisk: HIGH AND ifMaintainerLeaves: PROJECT_LIKELY_STALLS. That's the dependency tree you want to second-source plan around.

Worked examples — three archetypes that look the same on the surface

A widely-used data-validation library in the JavaScript ecosystem has 30,000+ stars, a contributors badge showing 547 people, and a recent commit history. The README is polished. Most teams adopt it without a second look.

Naive read: "547 contributors, popular, fine."

Concentration read: contributors.topContributorShare: 0.92 over the last 365 days. The other 546 lifetime contributors include automated dependency bots, one-typo-PR authors from years ago, and drive-by contributors whose work shipped once and never followed up. The current project is one person. busFactorRisk: HIGH. ifMaintainerLeaves: PROJECT_LIKELY_STALLS. The 30,000 stars are a popularity stat from years ago; the bus factor is a structural fact about today.

Archetype B: the niche library that's actually distributed

A specialised framework for embedded ML deployment has 3,200 stars, 84 lifetime contributors, and looks small from the outside.

Naive read: "Small project, probably one or two people, risky to depend on."

Concentration read: contributors.topContributorShare: 0.23. Eighteen contributors made meaningful commits in the last 90 days. The repo has clear ownership rotation across modules. busFactorRisk: LOW. ifMaintainerLeaves: MINIMAL_IMPACT. Star count understated the project; rolling-window concentration corrected it.

Archetype C: the high-concentration project where it's actually fine

A foundation-governed framework has a paid lead maintainer who personally writes 89% of commits in the last 365 days. The contributor list is small; the same person reviews almost every PR.

Naive concentration read: "topContributorShare 0.89 — bus factor 1 — HIGH risk."

Impact-weighted read: busFactorRisk: HIGH but the project has a foundation behind it, multiple paid co-maintainers funded but not currently shipping, an explicit succession plan, and a governance document. ifMaintainerLeaves: MODERATE_IMPACT — not PROJECT_LIKELY_STALLS — because the structural absorption capacity is real even if recent commits are concentrated. Concentration alone overstated the risk; the impact field corrected it. This is why concentration without impact is just trivia.

These three archetypes look superficially similar on stars and contributor count. They behave completely differently under any real measurement.

How to scan a dependency tree for bus-factor risk

For a dependency tree of more than ~50 packages, manual contributor-graph eyeballing isn't feasible. The operational pattern is to feed the dependency list to the GitHub Repo Intelligence actor and filter the output.

The input shape — explicit dependency list, mode set to dependency-audit, contributor enrichment turned on automatically by the mode:

{
    "compareRepos": [
        "owner-a/dependency-1",
        "owner-b/dependency-2",
        "owner-c/dependency-3"
    ],
    "mode": "dependency-audit",
    "compareToPreviousRun": true,
    "githubToken": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

The actor fetches each repo, computes 90-day and 365-day commit windows, calculates contributors.topContributorShare per repo, classifies bus factor as LOW/MEDIUM/HIGH/CRITICAL, and projects ifMaintainerLeaves impact as MINIMAL_IMPACT/MODERATE_IMPACT/PROJECT_LIKELY_STALLS. The output dataset has every repo scored.

The operational filter that surfaces second-source candidates from a dependency tree is the conjunction:

  • maintenance.busFactorRisk == "HIGH" (or CRITICAL)
  • AND maintenance.ifMaintainerLeaves == "PROJECT_LIKELY_STALLS"
  • AND (optionally) maintenance.trajectory in ["DECLINING", "COLLAPSING"] to prioritise the most urgent

That filter typically reduces a 200-package dependency tree to a 5-15 row "second-source planning" list — the dependencies where a maintainer departure would actually hurt and where the structural absorption isn't there. That's the actionable read.

For a category audit (instead of a known dependency list), the same actor scans up to 10,000 repos in a category with autoPartitionResults: true and emits the same per-repo bus factor fields. Useful when the question is "across this whole ecosystem, which projects are popular but structurally fragile?"

The complexity that's easy to underestimate from outside the actor:

  • Contributor pagination across GitHub's stats API
  • Ordering inconsistencies between /contributors and /commits endpoints
  • Distinguishing humans from automation accounts (Dependabot, Actions, license bots)
  • Computing weighted concentration over rolling windows
  • Joining concentration to release cadence and project age for impact context
  • Persisting state across runs for cross-run diff detection

Each piece is solvable. Together they're a maintained service, not an afternoon script.

What are the alternatives to bus-factor measurement?

There are roughly five approaches. Each makes different tradeoffs between effort, cost, and accuracy.

  1. Eyeball the contributors page — Open the GitHub /graphs/contributors view, scan the top bar. Free. Subjective. Catches the obvious 95%-one-author cases, misses the 70% concentration cases that are still risk. Doesn't scale past a handful of repos.
  2. Custom script against the GitHub API — Pull the contributor stats endpoint, compute concentration over a rolling window, classify risk. Owns the schema-drift problem, the rate-limit problem, the bot-vs-human disambiguation problem, and the impact-context problem. Possible. A maintained service, not an afternoon script.
  3. OSS Insight or GitHub Insights dashboards — Free, dashboard-style category views. Show contributor counts and commit graphs but typically don't compute rolling-window concentration as a single field, don't predict departure impact, and don't run on a schedule against a dependency list.
  4. Snyk, Sonatype, or similar enterprise supply-chain platforms — Strong on CVE scanning and license posture. Bus factor surfaces as a derived signal at best, not a primary classification. Pricing is typically tens of thousands of dollars per year per seat.
  5. A decision-intelligence actor — Turnkey rolling-window concentration, impact prediction, and cross-run diff. One of the best fits when the question is "across my dependency tree, which projects have a structural single-maintainer problem and what happens if the maintainer leaves?" The developer and open-source tools comparison breaks down feature differences across the actors in this category.

Each approach has trade-offs in effort, cost, depth, and how directly it answers the operational question. The right choice depends on how many repos you're auditing, whether you need a verdict or a metric, and whether bus-factor-plus-impact is the question you're actually asking.

Comparison table

ApproachOutputRolling-window concentrationImpact predictionScaleBest for
Eyeball contributors pageVisual graphNoNo1-5 reposOne-off curiosity
Custom GitHub API scriptWhatever you buildYou build itYou build it100s with engineeringBespoke needs
OSS Insight / GitHub InsightsDashboardsPartialNo10s/sessionTrend visualisation
Snyk / SonatypeCVE + license + derived healthPartialNo1000s/runPost-adoption security
Decision-intelligence actorbusFactorRisk + ifMaintainerLeaves + diffYesYesUp to 10,000/runDependency audits, due diligence

Pricing and features based on publicly available information as of May 2026 and may change.

Best practices for measuring bus factor

  1. Use rolling-window concentration, not lifetime counts. A 90-day or 365-day window is what reflects current state. Lifetime contributor counts hide the actual signal.
  2. Pair concentration with impact. A high topContributorShare is only risk if the project also has high criticality and weak governance. Concentration alone is a number; concentration plus impact is a verdict.
  3. Filter automation accounts out of the contributor graph. Dependabot, GitHub Actions, license bots, and bot-merged commits are noise in a bus-factor read. The actor handles this by separating bot commits during enrichment.
  4. Audit fleet-wide on a schedule. Bus factor changes over months as maintainers slow down or onboard help. A one-time audit decays in 90 days.
  5. Filter by busFactorRisk: HIGH AND ifMaintainerLeaves: PROJECT_LIKELY_STALLS. This is the operationally useful conjunction. Concentration alone produces too many false positives on small-but-fine utilities.
  6. Distinguish FEATURE_COMPLETE from at-risk. A small utility with one author and zero open issues is done, not dying. The actor's isFeatureComplete: true flag separates the two.
  7. Use bus factor as a second-source planning trigger, not a no-adopt rule. A HIGH bus factor signal tells you to plan a second source or vendor-paid alternative — not necessarily to avoid the dependency outright.
  8. Cross-reference HIGH bus factor with NEWLY_ABANDONED in scheduled runs. That's the highest-priority combination — concentrated maintenance plus a maintainer who's already slowing down.

Common mistakes when measuring bus factor

  • Mistake 1: Counting lifetime contributors. This is the most common mistake. A 547-contributor list usually reads as "healthy"; in practice the real bus factor is concentration over a recent window, often 1-3.
  • Mistake 2: Counting recent contributors as equal weights. A contributor who fixed one typo in the last 90 days isn't equivalent to the maintainer who shipped 90% of the commits. Equal-weight counts produce inflated bus factor reads.
  • Mistake 3: Treating bus factor 1 as automatically bad. A small focused utility, a finished tool with stable scope, or a foundation-governed project with a paid lead can all read bus factor 1 and still be acceptable. Concentration alone is not a no-adopt rule.
  • Mistake 4: Ignoring the impact half. topContributorShare: 0.92 on a 200-line CLI tool is fine. Same number on a core auth library is catastrophic. Skipping the impact field collapses two completely different risks into the same verdict.
  • Mistake 5: Auditing once and forgetting. Bus factor changes month over month. Maintainers slow down, contributors join, governance evolves. A green audit at adoption-time decays.
  • Mistake 6: Confusing bus factor with abandonment. Bus factor 1 means concentrated, not stopped. The maintainer is still active; the structural fragility is the point. Abandonment is a separate signal — the actor exposes both. See how to detect abandoned GitHub repos at scale for the abandonment-specific framing.

Mini case study — catching a hidden bus factor in a dependency tree

A hypothetical platform engineering team at a mid-size SaaS company has a dependency tree of roughly 200 direct production dependencies. Their previous bus-factor process was "trust the GitHub contributor count" — anything with more than 50 contributors was treated as healthy.

Before: No active bus-factor read. Adoption decisions were based on stars and the contributor badge. The team had three single-maintainer dependencies in the tree without realising it — all with contributor counts above 100, all with topContributorShare > 0.85 over the last 365 days.

After: They scheduled the GitHub Repo Intelligence actor on a weekly Apify Schedule with mode: "dependency-audit" and compareToPreviousRun: true. Cost: 200 repos × $0.15 = $30 per run, $1,560 per year. The first run flagged eight busFactorRisk: HIGH dependencies, three of them also ifMaintainerLeaves: PROJECT_LIKELY_STALLS.

Result: The team second-sourced two of the three high-impact ones (one had a viable fork-based alternative; one moved to a vendor-paid replacement) over the next quarter. The third — a small but critical config parser — they couldn't replace, so they hired the maintainer on a part-time consulting contract. Total ongoing cost roughly $1,560/year for the actor plus the consulting retainer, against a baseline risk of "one maintainer disappears, three production systems lose patch coverage." The single avoided incident from catching one of these projects before it stalled would have covered multiple years of audit cost at engineering loaded rates.

These numbers reflect one internal scenario. Results will vary depending on dependency tree size, team rates, and whether second-sourcing is a viable response in your context.

Implementation checklist

To set up a bus-factor audit on a dependency tree:

  1. Define the scope. Direct production dependencies (typical: 50-300) or full transitive tree (typical: 500-3000)?
  2. Get the dependency list. From package.json, requirements.txt, go.mod, Cargo.toml, or your SBOM. Map to GitHub owner/name pairs.
  3. Get a free GitHub token. No scopes needed. Triples API throughput.
  4. Choose mode. dependency-audit for the standard supply-chain read. The mode auto-enables contributor enrichment.
  5. Configure the input. Pass the dependency list via compareRepos. Enable compareToPreviousRun: true for cross-run diff.
  6. Run and read. Filter the output dataset on busFactorRisk == "HIGH" AND ifMaintainerLeaves == "PROJECT_LIKELY_STALLS" to get the second-source planning list.
  7. Schedule weekly. Apify Schedules, Monday morning. The KV-summary diff is the artefact that actually gets read.
  8. Wire into Slack or email. Apify webhooks pipe the diff to a channel. The team only reads what changed since last week.
  9. Cross-reference with CVE scans. The combination of HIGH bus factor + an open CVE on a dependency is the highest-priority signal in a supply-chain audit.

Limitations

  • Bus factor is a structural signal, not a behavioural one. A high topContributorShare tells you the structure is concentrated. It doesn't tell you the maintainer is about to leave. It tells you what would happen if they did.
  • Rolling windows are sensitive to vacation and burst patterns. A maintainer who took a 3-month sabbatical can produce a temporarily-misleading concentration read. Combine with commitActivity90d and commitActivity365d to spot the pattern.
  • Foundation-governed projects skew the read. A project with a paid lead maintainer doing 90% of commits but a strong governance structure isn't actually bus factor 1 in operational terms. The ifMaintainerLeaves field corrects for this; raw concentration alone overstates risk.
  • Bots and automation accounts need filtering. Dependabot and Actions commits inflate the contributor list. The actor filters these during enrichment, but custom scripts often miss this step.
  • Email-based maintainer identification is imperfect. Many contributors use GitHub's noreply addresses. Cross-account merging (one human contributing under multiple email addresses) can split a single maintainer into two contributor records. Concentration can read lower than reality.
  • Forecasts are probabilistic. ifMaintainerLeaves: PROJECT_LIKELY_STALLS is a weighted classification, not a guarantee. Some projects survive the loss of a dominant maintainer through community takeover; some don't.

Key facts about bus factor

  1. Bus factor is a concentration signal, not a count — the minimum number of contributors whose departure would stall the project, computed from rolling-window commit share.
  2. The lifetime contributors count on GitHub does not decay when contributors stop committing — it includes ex-contributors, drive-by PR authors, and bots, all weighted equally.
  3. A project with 547 lifetime contributors but topContributorShare: 0.92 over the last 365 days has a bus factor of 1, not 547.
  4. Bus factor 1 is not automatically bad — it depends on project criticality, scope, and governance. The actor's ifMaintainerLeaves field provides the impact half of the read.
  5. The xz-utils incident (CVE-2024-3094, March 2024) is the canonical real-world bus-factor cautionary tale — single-maintainer concentration was the structural precondition that made a social-engineering supply-chain attack viable.
  6. Two of three open-source projects commercial application teams depend on have become dormant, per Sonatype's 2024 supply-chain report — single-maintainer concentration is a leading indicator of this dormancy.
  7. The operationally useful filter for second-source planning is busFactorRisk: HIGH AND ifMaintainerLeaves: PROJECT_LIKELY_STALLS — concentration alone produces too many small-utility false positives.
  8. Decision-intelligence bus-factor measurement at $0.15 per repo is roughly 100-1000x cheaper than manual technical due diligence at engineering loaded rates for fleet-scale audits.

Short glossary

  • Bus factor — Minimum number of contributors whose departure would stall the project. Concentration metric, not a headcount.
  • Truck factor / lottery factor — Same metric as bus factor, different names. Truck factor is the term used in academic literature (Avelino et al. 2016).
  • topContributorShare — The fraction of commits authored by the single most active contributor over a rolling window (typically 90 or 365 days). 0.0-1.0.
  • busFactorRisk — Categorical risk classification (LOW/MEDIUM/HIGH/CRITICAL) derived from concentration plus signal context.
  • ifMaintainerLeaves — Impact prediction for what happens if the dominant maintainer departs (MINIMAL_IMPACT/MODERATE_IMPACT/PROJECT_LIKELY_STALLS).
  • Maintainer burnout — The well-documented pattern where a popular project's solo maintainer carries disproportionate work until they slow down or step away. Discussed in GitHub's open-source maintainers writing and Eghbal's Working in Public.
  • Second-source planning — The practice of identifying alternative implementations or vendor-supported replacements for high-risk dependencies before a maintainer departure forces the move.

Broader applicability

The pattern here — moving from naive headcount to rolling-window concentration to impact-weighted risk — applies far beyond GitHub. The same progression shows up across B2B lead scoring (impressions → engagement → ICP-match concentration), team resilience analysis (headcount → critical-skill concentration → succession risk), vendor risk management (vendor count → spend concentration → business-continuity exposure), and Apify actor reliability monitoring (run count → recent-window failure concentration → fleet health verdict).

Five universal principles apply:

  1. Headcount is a popularity stat. Concentration is a risk stat.
  2. Roll the window forward; lifetime totals lie because they don't decay.
  3. Pair concentration with impact — concentration alone is just a number.
  4. Filter on the conjunction (concentration AND impact) for actionable shortlists, not on the metric alone.
  5. Re-evaluate on a schedule — concentration changes month over month.

When you need this

Use rolling-window bus factor measurement when:

  • Adopting any open-source dependency that will run in production
  • Auditing an existing dependency tree for structural fragility
  • Doing technical due diligence on an investment-stage open-source project
  • Mapping a category for vendor risk and second-source planning
  • Screening dependencies in a high-stakes domain (cryptography, auth, payment, kernel-level tooling)
  • Replacing a quarterly subjective audit with a weekly automated read

You probably don't need this if:

  • The repo is internal and your team controls all the contributors directly
  • The project is a throwaway prototype where dependency risk is irrelevant
  • You only need a yes/no CVE check (use Snyk, Dependabot, or a similar scanner)
  • You already have direct CODEOWNERS-style relationships with the maintainers
  • The dependency has zero criticality (a single-maintainer fade-in animation library is fine)

How to calculate bus factor for a GitHub repo

Compute the share of commits authored by the top one contributor over a rolling 90-day or 365-day window. If that share is above ~0.8, the project has a structural bus factor of 1. The exact threshold varies by methodology — academic work like the Avelino et al. truck factor study uses a 50% concentration threshold for the top-N set. The actor exposes the raw topContributorShare value plus a categorical busFactorRisk classification, so consumers can filter on either the number or the verdict.

What is a good bus factor for a software project?

For a production dependency, a bus factor of 3 or higher is the conventional threshold — meaning at least three contributors would need to depart simultaneously for the project to stall. For internal team projects, the same threshold applies: aim for at least 3 people who can ship the codebase. For small focused utilities with limited scope, a bus factor of 1 can be acceptable if the project is feature-complete and the consumer can self-maintain on departure.

Is bus factor 1 always bad?

No. Bus factor 1 is a structural fact, not a verdict. Whether it's risky depends on project criticality and impact. A bus factor of 1 on a small finished utility with stable scope is fine. A bus factor of 1 on a core production library used by half your stack is catastrophic. The actor pairs concentration (busFactorRisk) with impact (ifMaintainerLeaves) so the verdict reflects both halves.

Bus factor vs truck factor — what's the difference?

There is no operational difference. They're two names for the same metric — the minimum number of contributors whose departure would stall the project. "Bus factor" is the older, community-coined term; "truck factor" is more common in academic literature (the Avelino et al. 2016 study is one of the canonical references). "Lottery factor" is a third name for the same idea, with a less morbid framing. All three measure concentration, all three care about recent activity rather than lifetime totals.

Common misconceptions

"A repo with 500 contributors has a bus factor of 500." No. The contributors badge is a lifetime count. The actual bus factor is concentration over a recent window. A repo with 500 lifetime contributors and one person doing 92% of last year's commits has a bus factor of 1.

"Bus factor 1 means the project is dying." No. Bus factor is a structural fact about who's currently shipping, not a prediction about whether they'll stop. A bus factor 1 project with an active engaged maintainer can be perfectly healthy today. The risk is what happens if the maintainer leaves — which the ifMaintainerLeaves field projects separately.

"Truck factor and bus factor are different metrics." They're identical. Different names for the same concentration signal. Use whichever your audience prefers.

"You can measure bus factor by looking at the contributor count on the GitHub page." No. The contributor count is a lifetime cumulative number — it includes everyone who ever pushed, weighted equally regardless of when or how much they contributed. The right signal is rolling-window concentration of recent commits.

"Foundation-governed projects with one paid lead maintainer have bus factor 1." Concentration-wise, yes. Impact-wise, often no. A foundation-backed project with succession planning, paid co-maintainers in reserve, and explicit governance can absorb a maintainer departure. The ifMaintainerLeaves field corrects raw concentration for governance context.

"Bus factor is the same as abandonment." They're different signals. Bus factor measures concentration today — the maintainer is still active, the structure is fragile. Abandonment measures whether activity has actually stopped. A repo can have bus factor 1 and be fully active. A repo can be abandoned regardless of bus factor. The two pair well, but they answer different questions.

Frequently asked questions

What is bus factor in software engineering?

Bus factor is the minimum number of contributors who would need to suddenly become unavailable for a software project to stall. It's named after the (morbid) thought experiment "what happens if the lead developer is hit by a bus." The metric is concentration-based, not headcount-based — a project with hundreds of lifetime contributors can have a bus factor of 1 if one person currently does most of the work. It's used in open-source risk assessment, technical due diligence, and dependency auditing.

How do I calculate bus factor for a GitHub project?

Compute the share of commits authored by the top contributor over a rolling 90-day or 365-day window. If topContributorShare > 0.8, the project has a structural bus factor of 1. Academic methodologies like the Avelino et al. truck factor framework extend this by computing the minimum-size subset of contributors whose combined share crosses a 50% threshold. The GitHub Repo Intelligence actor computes both the raw concentration and a categorical busFactorRisk field directly.

What is a good bus factor?

For production dependencies, aim for a bus factor of 3 or higher — at least three contributors who would need to depart for the project to stall. For internal teams, the same threshold applies. For small focused utilities, bus factor 1 can be acceptable if the project is feature-complete and self-maintainable on the consumer side. The right threshold depends on project criticality, not on a universal number.

Is bus factor 1 always bad?

No. A bus factor of 1 is a structural fact, not a verdict. A small focused utility with stable scope and a clear feature-complete state is fine at bus factor 1. A core production library used at scale is not. The actor models this with the ifMaintainerLeaves field, which projects departure impact as MINIMAL_IMPACT, MODERATE_IMPACT, or PROJECT_LIKELY_STALLS — concentration plus impact, not concentration alone.

What's the difference between bus factor and truck factor?

There is no operational difference. They measure the same thing — concentration of recent contributions across a project's contributor graph. "Bus factor" is the older community-coined term; "truck factor" is the common academic phrasing (see Avelino et al. 2016). "Lottery factor" is a third name for the same metric. Use whichever fits your audience.

How do I find single-maintainer dependencies in my project?

Pass your dependency list to a tool that computes rolling-window contributor concentration per repo. The actor's dependency-audit mode does this directly. Filter the output on busFactorRisk == "HIGH" AND ifMaintainerLeaves == "PROJECT_LIKELY_STALLS" to surface the dependencies that are both concentrated and structurally vulnerable. That filter typically reduces a 200-package tree to a 5-15 row second-source planning list.

How does the xz-utils incident relate to bus factor?

The xz-utils backdoor (CVE-2024-3094, disclosed March 2024 by Andres Freund) is the canonical real-world bus-factor cautionary tale. The xz-utils project had been maintained for years by a single developer experiencing publicly-acknowledged burnout. A new contributor spent roughly two years building trust through legitimate-looking contributions, gained co-maintainer access, and used that access to plant a backdoor in liblzma affecting OpenSSH on most Linux distributions. Single-maintainer concentration was the structural precondition that made the social-engineering takeover viable.

How often should I rerun a bus factor audit?

Monthly at minimum for production dependency trees, weekly for fast-moving categories (AI tooling, cryptography, web frameworks). Bus factor changes as maintainers slow down, contributors join, and governance evolves. Quarterly is too long — the early-warning signal of concentration plus declining trajectory wants weekly cadence to be useful. Cross-run diff (compareToPreviousRun: true in the actor) makes weekly cadence cheap to read because the team only reviews what changed.

Does bus factor replace CVE scanning?

No. They answer different questions. Bus factor measures structural fragility — what happens if the maintainer disappears. CVE scanning measures whether a specific version contains a known vulnerability. Both matter for supply-chain risk; neither replaces the other. The combination of HIGH bus factor risk plus an open CVE on a dependency is the highest-priority signal in a serious supply-chain audit.

Can I measure bus factor on private GitHub repositories?

The decision-intelligence actor uses GitHub's public Search API and only returns public repositories. Private-repo bus-factor analysis needs different tooling — GitHub's GraphQL API with appropriately scoped tokens, or self-hosted analytics. The framework here (rolling-window concentration plus impact) applies to either, but the data-collection layer differs.


Ryan Clinton publishes Apify actors as ryanclinton and builds developer tools at ApifyForge.


Last updated: May 2026

This guide focuses on GitHub repositories, but the same patterns — rolling-window concentration, impact-weighted risk, and scheduled diff-based reads — apply broadly to any concentration-risk problem, from team resilience analysis to vendor risk management to portfolio-wide actor reliability monitoring.