Product
Platform Agentic Code Scanner Unified Runner Tomosu Agents Indexes Solutions
Get Started
Scan your repo VS Code plugin Tomosu MCP GitHub App CodeRabbit FAQ
Resources
Case Studies Governance Impact TCO Calculator Download / Free Trial
Pricing
Plans and pricing
Company
About Blog News Contact Request Demo → Try Free Log in GitHub
Production Reliability · Code churn

Code Churn: Why the Files That Change Most Break Most

··11 min read·

Code churn is how much a file or component changes over a period of time: lines added, lines deleted, and how many separate commits touched it. High churn concentrated in a small set of files is one of the more reliable signals of where your next production bug will be, and a better one than file size or complexity on their own.

Quick answer

Code churn is the amount a file changes over a window of time, counted in lines added and deleted or in commits. Measured relative to file size it is a defect-density signal, not a vanity metric. A ranked churn list from git log takes about a minute to produce, and the riskiest entries are the ones that also have many authors and no clear owner.

Most teams already sense this. Every codebase has a billing module or an auth middleware that nobody wants to touch, and it is usually the one that gets touched every week. What teams rarely do is measure it. The data is already in git log, and pulling a ranked list of hotspots costs one command.

What is code churn, and how is it different from rework?

Code churn is the amount a file or component changes over a period of time, counted either as lines added plus lines deleted or as the number of separate commits that touched it. The term gets used interchangeably with rework and with hotspots, and tools define each differently. This is how they are used here.

TermWhat it measuresTypical windowQuestion it answers
Code churnLines added and deleted, or commits, per file3 to 12 monthsWhere does change happen?
Short-term churn (rework)New code reverted or rewritten soon after it was writtenDays to 2 weeksWas the code right the first time?
HotspotA file where churn stays high, usually combined with size, complexity or weak ownershipMonthsWhere should review effort go?
Relative churnChurned lines divided by file sizeAnyIs this file changing a lot for its size?

When a tool or a report quotes a churn number, check which of these it means before comparing it to anything.

Does code churn predict bugs?

The best-known evidence comes from Microsoft Research. Nachiappan Nagappan and Thomas Ball studied the changes between Windows Server 2003 and its Service Pack 1: roughly 45 million lines of code across 2,465 binaries. Their paper, Use of Relative Code Churn Measures to Predict System Defect Density (ICSE 2005), reports that their churn metric suite discriminated between fault-prone and not fault-prone binaries with an accuracy of 89.0 percent.

The important word is relative. Raw churn mostly tracks size, because big files change more by virtue of being big. The useful measures normalise it: churned lines divided by total lines, files churned divided by file count, and how many weeks a component kept changing. Relative churn predicted defect density. The paper is explicit that absolute churn measures are poor predictors on their own.

Two things follow for a working team:

How much to read into it

The study covers one very large codebase, in 2005, in C and C++. Treat 89.0 percent as evidence that the signal is real, not as the accuracy you will get on your repository.

How do you measure code churn with git?

No tool is needed for a first pass. Run these from the root of any repository. The outputs below are from the Celery repository, over the twelve months to November 5, 2026 (commit 6fcdbf9), with tests excluded so the list shows production code.

Commits per file

The simplest churn measure: how many separate commits touched each file.

Shell · commits per file
git log --since="12 months ago" --no-merges --name-only --format="" \
  -- '*.py' ':!t/' \
  | grep -v '^$' | sort | uniq -c | sort -rn | head -8

     28 celery/canvas.py
     25 celery/backends/base.py
     22 celery/backends/redis.py
     18 celery/app/task.py
     17 celery/worker/request.py
     16 celery/worker/consumer/consumer.py
     16 celery/app/defaults.py
     15 celery/app/base.py

Change '*.py' to your own language extension and ':!t/' to wherever your tests live. The :! prefix is git’s pathspec syntax for “exclude”.

Lines churned per file

Commit counts treat a one-character typo fix the same as a rewrite. Adding --numstat counts lines added plus lines deleted instead.

Shell · churned lines per file
git log --since="12 months ago" --no-merges --numstat --format="" \
  -- '*.py' ':!t/' \
  | awk '$1 != "-" { churn[$3] += $1 + $2 } END { for (f in churn) print churn[f], f }' \
  | sort -rn | head -8

852 celery/backends/redis.py
620 celery/canvas.py
611 celery/backends/base.py
470 celery/beat.py
463 celery/app/base.py
389 celery/worker/request.py
288 celery/backends/database/__init__.py
276 celery/app/trace.py

The $1 != "-" check skips binary files, which --numstat reports as dashes. A file near the top of both lists is a real hotspot. One that appears in only a single list is usually either many tiny edits or one large rewrite.

How concentrated is it?

In Celery’s case, 20 of the 161 Python files under celery/ account for 59 percent of all file changes in the year. Most repositories look like this. Change piles up in a small set of files, and those files deserve review time that a flat “every PR gets the same look” process never gives them.

To make the numbers relative, in the spirit of the Microsoft study, divide each file’s churned lines by its current line count from wc -l. A short file near the top of that ranking is being rewritten over and over.

Which high-churn files are riskiest?

Churn tells you where change happens. It does not tell you whether anyone understands the file it is happening to. The riskiest files tend to combine three things: high churn, many different authors, and no single person who made most of the changes. Every edit then gets reviewed by someone holding part of the mental model.

This loop adds author counts and the top author’s share to the hotspot list.

Shell · churn plus ownership
git log --since="12 months ago" --no-merges --name-only --format="" -- '*.py' ':!t/' \
  | grep -v '^$' | sort | uniq -c | sort -rn | head -5 \
  | while read -r commits file; do
      authors=$(git log --since="12 months ago" --no-merges --format='%ae' -- "$file" | sort -u | wc -l)
      top=$(git log --since="12 months ago" --no-merges --format='%ae' -- "$file" \
            | sort | uniq -c | sort -rn | head -1 | awk '{print $1}')
      printf "%4s commits %3s authors  top author %3s%%  %s\n" \
        "$commits" "$authors" "$((100 * top / commits))" "$file"
    done

  28 commits  22 authors  top author  14%  celery/canvas.py
  25 commits  19 authors  top author  12%  celery/backends/base.py
  22 commits  16 authors  top author  18%  celery/backends/redis.py
  18 commits  11 authors  top author  38%  celery/app/task.py
  17 commits  14 authors  top author  11%  celery/worker/request.py

For an open-source project like Celery, many authors per file is normal and healthy. That is how community projects work, and maintainers review every pull request. Inside a company, the same pattern on a billing or an auth module means something else. If 19 people changed backends/base.py in a year and nobody made more than 12 percent of the changes, there is probably nobody who can say what that file is supposed to guarantee.

Two caveats on these numbers

Author counts use the commit email, so one person with a work address and a personal address counts twice. A .mailmap file fixes that. And a high top-author share is not automatically good, because it can also mean the file’s bus factor is one.

The cheapest fix is a CODEOWNERS entry for your 10 to 20 hottest files. It does not make anyone smarter about the code, but it puts the person with the most context on every pull request that touches it, and in a high-churn file that is most of the pull requests.

Does AI-generated code increase code churn?

The published data is suggestive rather than conclusive. GitClear analysed 211 million changed lines written between January 2020 and December 2024, from repositories owned by Google, Microsoft, Meta and enterprise C-Corps, and reports increases in short-term churn over that period alongside two shifts it does quantify: lines associated with refactoring fell from 25 percent of changed lines in 2021 to under 10 percent in 2024, and lines classified as copy-pasted rose from 8.3 percent to 12.3 percent in the same period (GitClear, 2025). That is a correlation across many companies over the years in which AI coding assistants spread, not a measured cause.

What matters more for review is where the extra change lands. Coding agents do not change where churn happens. They change how much of it there is.

An agent edits wherever the prompt points it, and prompts point at the places people already work: the request handler that needs another field, the shared client that needs another option, the config module that needs another flag. So the files that were hot before agents get hotter, faster.

The agent also arrives with no history. It does not know that a file like request.py has been changed 17 times this year, which of those changes got reverted, or which one started the last incident. A context file such as CLAUDE.md or AGENTS.md can describe the architecture, but it rarely says “this file is fragile, be careful here”, and the agent still grades its own work when it reports that it is done.

A hotspot used to get a handful of changes a month from people who had been burned by it before. Now it can get several a week, some written by something that has never seen it break.

Churn data is how you notice that shift before it shows up as an incident. The same reasoning applies to a single change: see How to Identify High Risk Pull Requests for the other signals that belong next to churn.

How do you reduce risk in high-churn files?

A ranked list is only useful if it changes how the team works. Five things that do:

  1. Put owners on the top 20. One CODEOWNERS line per file. This is the cheapest change on the list and usually the most effective.
  2. Raise the review bar for pull requests that touch them. A second reviewer, or a reviewer from the owning team, for any PR touching a top-20 file. Everything else keeps the normal process, so review effort goes where change is concentrated.
  3. Write the tests the file is missing. High churn plus thin tests is the worst combination. Check coverage on the hotspots specifically, not the repository average.
  4. Split files that change for unrelated reasons. If one config module changes for worker settings, broker settings and storage settings, that is three files sharing one name. Splitting them spreads the churn and shrinks every review.
  5. Re-run it every quarter. Hotspots move. A file that cooled off after a refactor should not keep its extra process, and a newly hot one should get it.
What not to do

Do not turn churn into a per-developer metric. High churn against someone’s name usually means they were handed the hardest part of the codebase. Measured per person, the number gets gamed within a quarter and stops telling you anything about the code.

What tools measure code churn?

The right tool depends on which question you are asking, and none of these replaces the others.

If you only need a hotspot list once a quarter, git is enough. Reach for a tool when you want the numbers tracked over time or combined with other signals.

How does churn fit into a production reliability score?

Churn on its own says where change happens. It does not say whether a specific change is safe. That is why it works best as one input among several rather than as a verdict.

That is how Tomosu uses it. The Production Reliability Index is a trendable score for how ready code is for production, and it rolls up from eight sub-indexes. Code Volatility is one of them, covering churn and hotspot density. It sits next to the Fragility Index, which looks at reliability patterns in the code itself, such as timeouts, retries, resource cleanup and error handling. A hot file with missing timeouts reads very differently from a hot file that is mostly configuration.

Tomosu reads the standing codebase as well as the diff, which matters most for exactly these files: a small change to a hotspot can reach code the pull request never touched. That gap is the subject of What a Repository-Wide Review Finds That a PR Diff Misses. Each finding comes with a before and after code change that a person accepts or rejects. Where runtime signals are connected, sub-indexes such as Drift and Runtime Signals join the score; where they are not, they stay out rather than being estimated.

See Code Volatility on your own repository →

Key takeaways

Frequently asked questions

What is code churn?

Code churn is the amount a file or component changes over a period: lines added and deleted, and how many commits touched it. It is usually measured per file over the last 3 to 12 months.

Is high code churn bad?

Not by itself. New features churn while they are being built, and that is expected. Churn becomes a warning sign when it stays high in the same files month after month, especially in code that should be stable, like auth, billing or shared clients.

How do you measure code churn?

With git log --numstat for lines added and deleted per file, or git log --name-only for commit counts per file. To compare files fairly, divide churned lines by each file size.

Does code churn predict bugs?

Research suggests it does when measured relative to size. A Microsoft study of Windows Server 2003 found that relative churn measures separated fault-prone binaries from the rest with 89.0 percent accuracy. Absolute churn on its own predicted poorly.

What is the difference between code churn and a hotspot?

Churn is the measurement. A hotspot is a file where churn is consistently high, usually combined with size, complexity or weak ownership.

What is a good code churn rate?

There is no universal benchmark, because churn depends on the window, the language and how active the project is. A file changing a lot during a new feature is normal. The more useful comparison is your own repository against itself: which files stay at the top quarter after quarter.

Does AI-generated code increase code churn?

The published data is suggestive rather than conclusive. GitClear reports increases in short-term churn across 211 million changed lines written between 2020 and 2024, together with refactored lines falling from 25 percent of changed lines in 2021 to under 10 percent in 2024 and copy-pasted lines rising from 8.3 percent to 12.3 percent. Those are correlations across many companies, not a measured cause.

What causes high code churn?

Usually one of four things: a feature still under active development, unclear or shifting requirements, a file that mixes unrelated responsibilities so every change lands in it, or code that keeps breaking and getting patched. Only the last two are a problem by themselves.

Parsa Mohammadi, Technical Marketing Lead at Tomosu AI
About the author

Parsa Mohammadi

Technical Marketing Lead at Tomosu AI

Parsa writes about production reliability, pre-merge risk, and how engineering teams govern AI-generated code. He works with the founding team at Tomosu AI on what the platform measures and how teams put it to use.

Connect on LinkedIn →

The files that change most are the files a review process should treat differently. Tomosu scores Code Volatility next to seven other sub-indexes, so a hotspot with missing timeouts is told apart from a hotspot that is mostly configuration. Assess your repository →

Request Demo →