Knowledge Silos and Bus Factor: How to Measure and Reduce Them

Bus factor is measurable from data you already have in git. This guide shows the commands, how to read the results, and a practical plan to spread knowledge.

By The OpenVisio Team · · 12 min read

Every team has a module that only one person really understands. Usually it is the billing reconciliation job, the custom auth middleware, or the build pipeline someone wrote in a heroic week three years ago. Nobody decided to create that silo. It formed because the same person kept getting the tickets in that area, because they were fastest, and because reviewing their work felt like a formality.

The bus factor (sometimes called truck factor) is the number of people who would have to leave before a part of the system has nobody left who can safely change it. For many modules in many codebases, that number is one. The good news is that you do not need a survey or a consultant to find those modules. Your version control history already contains most of the signal, and a few shell commands will surface it. This guide covers how to measure ownership concentration, how to interpret the numbers without fooling yourself, and how to reduce silos with deliberate, low-ceremony habits.

Key takeaways

  • Bus factor is a property of each module, not of the whole repository. Measure it per directory or per service.
  • Git history gives a reasonable first approximation: who authored most of the recent changes, and who reviewed them.
  • Commit counts lie in both directions. Combine authorship with recency, review participation and a quick conversation.
  • The modules that matter most are the intersection of single ownership, high business criticality and high change frequency.
  • Reduce silos through review rotation, paired tickets, written tours and runnable tests, not through big documentation projects.
  • Track the number of modules with two or more active contributors each quarter. That is a metric a team can actually move.

Why knowledge silos form

Silos are a side effect of efficiency. When a ticket lands in the payments area, the person who knows payments can fix it in an hour while anyone else would need a day. Under deadline pressure, the hour wins every time. Repeat that for two years and you have a person who is the only one who can work in payments, and a team that has quietly agreed not to learn.

Three other forces make it worse. First, review that rubber-stamps: if the expert's PRs are approved by someone who does not understand them, review spreads no knowledge at all. Second, missing tests: when the only way to know a change is safe is to ask the expert, every change routes through them. Third, undocumented intent: the code says what happens, but not why the retry count is seven or why the job runs at 03:10 instead of midnight. That reasoning lives in one head.

None of these are character flaws. They are incentives. Fixing silos means changing the incentives slightly, so that spreading knowledge is the default path rather than an extra chore.

Measuring ownership with git

Start with authorship concentration per directory. The simplest view is a shortlog scoped to a path and a time window.

# Who has committed to this area in the last 12 months?
git shortlog -sn --no-merges --since="12 months ago" -- services/billing/

# Same thing, but count by email to merge duplicate names
git shortlog -sne --no-merges --since="12 months ago" -- services/billing/

If one name accounts for most of the commits, that is a candidate silo. Commit counts are noisy, so cross-check with lines of surviving code. git blame tells you who last touched each line that exists today.

# Surviving lines by author for one directory
git ls-files services/billing/ | grep -E '\.(ts|go|py)$' | while read f; do
  git blame --line-porcelain -w -M -C "$f" | grep '^author ' 
done | sort | uniq -c | sort -rn | head

The -w flag ignores whitespace changes, and -M -C follow moved and copied lines, so a reformat or a file move does not steal ownership from the person who wrote the logic. If you want this in a tidier table, the open source git-fame tool (pip install git-fame) produces per-author line, commit and file counts for a path.

To see the whole repository at once, loop over top-level directories and report the share of the top author.

for d in $(git ls-tree -d --name-only HEAD services/); do
  total=$(git log --no-merges --since="12 months ago" --format='%ae' -- "$d" | wc -l)
  top=$(git log --no-merges --since="12 months ago" --format='%ae' -- "$d" \
    | sort | uniq -c | sort -rn | head -1)
  echo "$d total=$total top=$top"
done

A directory where the top author has well over half of a meaningful number of commits, and nobody else has more than a handful, has an effective bus factor of one for practical purposes.

Add review data

Authorship misses an important channel: reviewers often know code they never wrote. If you use GitHub, the gh CLI can pull who reviewed merged PRs that touched a path.

gh pr list --state merged --limit 200 --search "billing in:title,body" \
  --json number,author,reviews \
  --jq '.[] | [.number, .author.login, ([.reviews[].author.login] | unique | join(","))] | @tsv'

Search by path is not supported directly by gh pr list, so a label or naming convention helps, or you can use the GitHub API to list PR files. The goal is a rough answer to one question per module: besides the main author, who has looked closely at this code recently?

Watch for the misleading cases

Git data is a starting point, not a verdict. Some patterns to correct for:

  • Bulk changes. A person who ran a codemod across the repo will appear to own everything. Exclude known mechanical commits with git log --invert-grep --grep="codemod" or maintain a .git-blame-ignore-revs file and pass --ignore-revs-file to blame.
  • Pairing. Pair-programmed commits often credit only one author. If your team pairs, encourage Co-authored-by: trailers so the history reflects reality.
  • Departed authors. The top author may already be gone. Filter to people who are still on the team. That is the number that matters.
  • Stable code. A module that nobody has touched in two years may have a bus factor of zero and be completely fine, because it never changes. Risk comes from code that changes and that only one person can change.

Prioritizing which silos matter

You will find more silos than you can fix. Rank them using three inputs.

InputHow to get itWhy it matters
Ownership concentrationTop author share from the commands aboveMeasures how much knowledge is in one head
Change frequencygit log --since="6 months ago" --format= --name-only -- <dir> | wc -lCode that changes often needs people who can change it
CriticalityAsk: does an outage here lose money, data or trust?Decides how bad a slow fix would be

A module that scores high on all three is your top priority. A frequently changed internal tool with one owner is a medium priority. A rarely changed, low-criticality script with one owner can wait. The hotspot method in mapping technical debt uses the same churn data, so you can reuse the work.

It also helps to look at structure, not just history. A single-owner module that dozens of other modules import is riskier than a leaf that nothing depends on, because changes there ripple. A dependency graph or the dependents view in a code map makes that visible quickly.

Reducing bus factor without a documentation project

The instinct is to ask the expert to "write everything down". That rarely works. The document gets written once, is too abstract to be useful, and is out of date within a quarter. Smaller, recurring habits do better.

Rotate reviewers deliberately

Make the second person in a silo the required reviewer for that area for a quarter. Use CODEOWNERS to encode it:

# .github/CODEOWNERS
/services/billing/  @alice @dmitri
/services/search/   @sam @priya

Then set an explicit expectation: the reviewer is expected to understand the change well enough to explain it, and is encouraged to ask questions in the PR rather than approve. Questions in PR threads become searchable knowledge for the next person too. The code review guide for unfamiliar code gives the reviewer a method so this does not feel like a test.

Pair the next ticket, then swap

For the top silos, take the next real ticket in that area and assign it to the non-expert, with the expert as a pairing partner who is not allowed to drive. The ticket after that, the non-expert works alone and the expert reviews. This costs a few hours of slower delivery and buys a second person who has actually shipped in the code.

Record a tour, not a manual

A 20-minute walkthrough of how a request flows through the module, with links to the real files, transfers more than a long design document. Record it, store the outline next to the code, and update it when the flow changes. Running a codebase walkthrough covers how to structure one so it stays useful.

Capture intent where it lives

Most silo knowledge is the "why". Push it into the places people will look when they need it:

  • A comment above the magic number explaining where it came from.
  • An architecture decision record for the large choices, linked from the module README. See the ADR guide.
  • A characterization test that pins surprising behavior, named after the behavior, such as test_refund_after_settlement_creates_reversal_not_credit.

Make it safe to change without the expert

If the only way to know a change is safe is to ask Alice, Alice is the silo regardless of how much is documented. Tests, a runnable local setup and a staging environment where the module can be exercised are the most durable knowledge transfer you can build.

A quarterly bus factor review

Turn this into a lightweight routine. Once a quarter:

  1. Run the ownership script across top-level modules and paste the output into a shared doc.
  2. Filter to current team members only.
  3. Mark each module as one, two, or three-plus active contributors in the last six months.
  4. Pick the three highest-priority single-owner modules using the ranking table above.
  5. For each, choose one action: reviewer rotation, a paired ticket, a recorded tour, or a test gap to close.
  6. Next quarter, check whether those three moved to two contributors.

The metric to track is simple: the count of critical modules with at least two people who have shipped a change there recently. It is concrete, it moves when you do the work, and nobody can game it without actually spreading knowledge.

Where tools help

Ownership data tells you who knows a module. It does not help the second person learn it. That is the slower part, and it is where a good map of the code pays off. OpenVisio builds a map of a repository in the browser, so a newcomer to a silo can open the Explore view to see what the module depends on and what depends on it, or follow a guided Tour stop by stop before their first paired ticket. Combined with git ownership data and a rotation plan, it shortens the time it takes for a second person to become genuinely useful in code they did not write.

Bus factor is not a number to report upward and forget. It is a list of specific modules and specific people, and a habit of moving one module at a time from one owner to two.

bus factorknowledge siloscode ownershipengineering managementgit

See it on your own repo

Paste a GitHub URL and get the day-one walkthrough — free, in your browser.

Index a repo

Keep reading