What Is Code Churn? How to Measure It and When It Signals Trouble
What is code churn? It is code that gets rewritten or deleted shortly after it was written, and it often reveals shifting requirements, architectural friction, or late reviews before deadlines slip. This guide defines it precisely, shows how to calculate churn rate from Git data, explains how to separate healthy churn from harmful churn, and outlines what to do when the number climbs.
Code churn is code that gets rewritten, deleted, or heavily modified shortly after it was first written. It matters because it often shows friction in a project before a deadline slips: requirements that keep moving, an architecture that fights the team, or reviews that happen too late. A high number is not automatically bad, and a low number is not automatically good.
If you are asking what is code churn in practical terms, the useful answer has four parts: a precise definition, a way to calculate it from Git data, a way to separate healthy churn from the harmful kind, and a plan for what to do when the number climbs. The sections below take those in order.
Code Churn Defined: Lines Rewritten, Not Just Lines Changed
Code churn is code that is added and then modified or removed within a short window. Most teams use a window of two to four weeks, but that is a choice, not a standard. A team that ships weekly may pick two weeks; a team with long review cycles may need four. What matters is that you pick one and keep it fixed so the trend means something.
The churn rate is the share of newly written lines that get changed or removed inside that window. Suppose a developer ships 400 lines on Monday and 250 of them are replaced by Friday. The churn rate for that work is roughly 60 percent (250 divided by 400, about 62 percent).
What churn is not
Churn is easy to confuse with several neighboring ideas, and mixing them up leads to bad readings.
- Raw change volume. A large feature adds thousands of new lines, but that is growth, not churn. Rewriting last week's pull request is churn.
- Rework. This is the broader, human-level term for redoing work, including fixes after QA or reopened tickets. Churn is the code-level measurement that often reveals it, but rework can also happen without much visible churn, for example when a design is scrapped before any code is written.
- Legacy refactoring. Editing code that has been stable for months or years is usually not churn, because the window has long passed. It is deliberate maintenance.
- Change pressure. This describes how much merging is happening and how large those changes are over a period, such as merge volume and code churn together. Churn is one input to change pressure, not a synonym for it.
Keeping these separate matters when you talk to your team. "We have a lot of change" and "we keep redoing the same work" call for very different conversations.
How to Measure Code Churn from Your Git History
You can get a workable churn rate from data you already have. The method is the same whether you do it by hand or with a tool.
- Pick a window. Choose the number of days (14 or 21 are common) after which new code is considered settled.
- Take the lines added. Count lines added in merged work during a chosen period, such as a sprint or a calendar month.
- Count what was touched again. For those lines, count how many were modified or deleted within the window after they were written.
- Divide. Churned lines divided by lines added gives the churn rate for that period.
Where the data lives
Git history on GitHub is the source, but the level you read it at matters. Pull-request-level views are generally more reliable than commit-level ones. Squash merges collapse many commits into one, and rebases rewrite commit history, so counting commits can both hide real rework and invent fake rework. Commit counts do not equal churn.
For a manual approximation, git log --numstat lists lines added and deleted per file per commit, and git blame shows which commit last touched each line, so you can see how recently a line was written. Check the exact flags against your Git version before building a script around them, and expect the result to be rough: blame attributes a line to its latest change and cannot tell you what was replaced. Platforms can automate this. As of 2026, Progress calculates churn and change pressure from connected GitHub and Linear data so you do not maintain scripts yourself.
Pitfalls that inflate the number
Exclude noise before you trust any figure:
- Generated files and build output
- Lockfiles such as package-lock.json or yarn.lock
- Vendored or third-party code copied into the repo
- Formatting-only commits, such as running a new linter across the codebase
- Mass renames and file moves
One auto-formatter run can make a quiet month look like a crisis. If a number jumps suddenly, check for one of these first.
Healthy Churn vs. Warning-Sign Churn
Some churn is a sign of a team doing its job well. Early prototyping produces it, since you write something to learn whether the approach works. Exploring an unfamiliar problem produces it. So does responding to review feedback: a reviewer who catches a flawed design in a pull request is creating churn, and that is exactly the outcome you want from review.
The question is not whether churn exists but what shape it takes. These patterns deserve a closer look:
- Concentration in one module. If most churn lands in a single service or directory, the problem is probably there, in its design, its requirements, or its test coverage, rather than spread across the team.
- Repeated rewrites of the same file. A file that is substantially rewritten three times in six weeks is telling you something about its purpose or boundaries.
- Churn after QA or near a release. Code reworked late is code with less time to prove itself, and late rework often means a problem was found later than it should have been.
- Churn rising while throughput falls. If the team is changing more code but closing fewer roadmap items, capacity is going into redoing work.
Context changes the reading
A new startup product in discovery mode should tolerate far more churn than a mature billing service. In discovery, rewriting is how you find the right answer, and low churn might even mean the team is committing too early. In a payments or billing system, the same level of rewriting would suggest instability in code where mistakes are expensive.
Skip the universal benchmark
There is no single good percentage. Published research on churn exists, including GitClear's analyses of code churn and AI-assisted coding and the DORA reports from Google, and both are worth reading for direction. But their figures reflect their own samples, definitions, and windows, which may not match yours. If you cite a number, name the source and year. For decisions, establish your own baseline: measure a few months of your own repos, then watch deviations from that baseline, by module and by work stream.
What Causes High Code Churn
When churn rises, the cause is rarely "developers writing bad code." It usually sits in one of three layers.
Process causes
- Vague or shifting requirements, so the target moves after code is written
- Tickets started before acceptance criteria are settled
- Stakeholder feedback that arrives after the work is built rather than before
Technical causes
- Unclear architecture, where developers are not sure where a change belongs and guess
- Missing tests, which let regressions through and create fix-after-fix cycles
- Tangled modules where one change forces edits across many files, so each change disturbs recent work
Team causes
- Large pull requests that receive shallow review, so problems surface later
- Junior engineers who do not get feedback until a PR is complete
- Context-switching and overload, which lead to half-finished work that must be redone when someone returns to it
A worked example
Imagine a ticket for a discount calculation. It is marked done, then reopened after a product review, reworked, and reopened again after finance points out a rounding rule. By the third round, the same function has been rewritten each time. The code churn in that function is high, but the developer is not the problem. The requirements were never settled, and each round exposed a new constraint. Better coding would not have prevented it. A short conversation with finance before the first line was written would have.
That is the value of looking at where churn sits and what the tickets around it look like. The same number can come from a requirements problem, an architecture problem, or a review problem, and the fix differs for each.
Why Churn Is Risky for Releases and Team Health
High churn affects three things: the release, the roadmap, and the people doing the work.
Deployment risk
Code that was heavily modified recently has had less time in production to prove itself. When a code area has high churn and also high merge volume ahead of a release, change pressure rises: more changes, landing faster, in places that have not settled. That combination is where regressions tend to come from, and it is a reason to add review attention, test coverage, or a staged rollout to those areas specifically.
Delivery risk
Churn consumes capacity without moving roadmap items forward. This explains a common puzzle: velocity looks fine, pull requests are merging, yet initiatives stall. If a meaningful share of that activity is rewriting recent work, the team is busy but not advancing. Reading churn next to initiative progress shows whether activity is turning into delivery.
Human cost
Repeated rework is demoralizing. Rebuilding something you finished last week, especially for reasons outside your control, wears on people, and sustained rework can precede slowing momentum or burnout. That is why churn is worth reading alongside team sentiment and pace rather than on its own. A rising churn trend combined with a slowing team and flatter mood is a stronger signal than any one of them.
A caveat on using it
Churn is a signal to investigate, not a performance score for individual developers. It depends heavily on what someone is assigned: the engineer on an exploratory spike will show more churn than the one on routine maintenance. Ranking people by it also invites gaming, such as splitting changes oddly or avoiding necessary rewrites, which makes the metric useless and the code worse.
How to Reduce Churn Without Slowing the Team Down
The goal is not zero churn. It is catching the avoidable kind earlier, when it is cheap.
- Clarify before coding. Use a lightweight definition of done on each ticket, and write a short design note for non-trivial work. A half-page that names the approach and the open questions is often enough to expose a disagreement before it becomes a rewrite.
- Shrink the unit of work. Smaller pull requests get better review and surface problems sooner. Feature flags let partial work merge safely, so feedback arrives on small increments instead of a finished block.
- Get early feedback to newer engineers. A fifteen-minute check-in on approach before they build is cheaper than a full rewrite after review.
- Review churn at the right level. Look at the trend by module and by work stream in retros or weekly leadership check-ins. Avoid per-person leaderboards. Ask what the cluster tells you: unclear requirements, a fragile module, or a review bottleneck.
None of this adds heavy process. Each item moves a decision earlier, which is where changes cost the least.
Tooling can remove the manual work of tracking it. Progress surfaces churn and change pressure alongside stalled work and team momentum, so a lead sees the signal with its context instead of building and maintaining a dashboard. As of 2026 it draws on connected tools such as GitHub and Linear.
Find the Module Where Your Churn Clusters
Churn is a diagnostic clue about requirements, architecture, and process, not a verdict on the developers who wrote the code. A high number tells you where to look; it does not tell you who to blame. The useful questions are where the rewriting happens and why that spot keeps getting reworked.
This week, compute a baseline for one repository. Choose a window, exclude lockfiles and generated files, calculate the churn rate for the last couple of months, and break it down by module. Then look for the one directory where churn clusters and read the tickets behind it. That conversation will likely teach you more than the percentage itself.