There is a file in the MongoDB codebase that has been touched 62 times in the last year.
It is 2,273 lines long. Its cyclomatic complexity is 926 — in a codebase where the average is 53.
replication_coordinator_impl.cpp
Every engineer who has worked near the replication layer knows it. The name alone is enough to produce a familiar reaction: a slight tension, a quick mental calculation of whether the ticket they just picked up is going to touch it.
That reaction is data. And it is worth understanding precisely.
The Instinct Is Right, but the Diagnosis Is Usually Wrong
The standard response to a file like this is to call it a legacy problem. It accumulated over years. It was nobody’s deliberate choice. And technically that is true — but it is also not useful, because it suggests the answer is patience. Wait long enough, assign it to a cleanup sprint, and eventually it will be tamed.
The instinct is correct. The diagnosis is wrong.
The problem is not that the file is complex. A tangled algorithm sitting untouched in one module is, in practice, fine. Nobody has to think about it. It sits in the repository, doing its job, and engineers route around it at no particular cost.
The problem is not that the file is frequently modified either. A simple file that changes every sprint is easy to reason about. Changes are small, reviewable, and contained.
The dangerous combination is both at once: high complexity and high churn, in the same file. Every change is hard to reason about — and it happens constantly.
In the MongoDB repository, 187 files have cyclomatic complexity above 100 and more than 20 commits. That is not a legacy problem. It is a structural signal.
What the Signal Is Actually Telling You
The Complexity × Churn formula was first described by Adam Tornhill in Your Code as a Crime Scene. The insight is simple but non-obvious: static analysis tools measure how complex a file is. Churn tells you how often that complexity must be navigated under pressure. Multiply them, and you get a proxy for where change-related risk actually concentrates.
Most engineering teams measure these separately, if at all. Complexity scores from static analysis. Commit counts from the git log. But kept separate, neither metric surfaces the right thing. A high-complexity file with no churn is interesting trivia. A high-churn file with no complexity is routine maintenance. It is only the intersection that marks a file as structurally dangerous.
Here is what that intersection is telling you: these are the files where the next unexpected delay already lives. A two-day ticket that touches one of them becomes a two-week investigation — not because the individual change is hard, but because the local change has non-local consequences that were invisible when the work was scoped.
How Files End Up Here
Nobody plans this. The trajectory is always the same.
The file starts as fifty clean lines. One function, one responsibility, one clear reason to exist. Then a second concern arrives — something that was almost unrelated, but not quite, and creating a separate module felt like overengineering. So it goes here. Then validation gets added. Then logging. Then a configuration flag, because one customer needed a slightly different behavior and the existing structure made this the path of least resistance.
Eighteen months later, the file has absorbed four concerns that were each individually defensible additions. No single engineer made a bad decision. The accumulation was the problem.
This process is essentially invisible to static analysis. The file does not announce that it has changed shape. No lint rule flags the moment when the third unrelated concern arrived. Only the commit history preserves a record of the trajectory — and only the combination of complexity measurement and churn makes that record legible.
The Real Cost
When a file reaches this state, the consequences are not evenly distributed.
Complexity × Churn hotspots tend to develop a small permanent expert class — two or three engineers who have been working near this area long enough to hold the context in their heads. For tickets that touch the hotspot, they become the default reviewers, the default escalation path, and the default 2am contact when something goes wrong.
This is not sustainable for the engineers involved. It is also a risk that compounds: as context concentrates, bus factor drops. The moment one of those engineers leaves, the team discovers how much of the file’s behavior was oral tradition rather than documentation.
For everyone else, the cost is invisibility. A ticket that looks like a two-day change touches the hotspot, expands in scope mid-sprint, and becomes an explanation to a stakeholder about why the estimate was wrong — not because of carelessness, but because the blast radius was not legible before the work started.
Your git history recorded all of this. It has been recording it for years. The signal is there.
Reading the Signal Before the Ticket
The practical question is not whether you have hotspots — you almost certainly do — but whether you can read the signal before it costs you.
The Complexity × Churn calculation requires no special tooling to start. A complexity tool (many exist for most languages) combined with git log --oneline -- <file> gives you the raw materials. Sort by product, and the list that comes back will be recognizable to anyone who has been on the team for more than a few months.
What is harder to derive manually is the coupling context: which other files move with the hotspot when it changes. That is where blast radius analysis (which we covered in the previous post) connects directly to hotspot analysis. The most dangerous configuration is a high-complexity, high-churn file that is also tightly coupled to components owned by other teams. Those changes are not just hard to reason about locally — they are coordination events that look like local changes.
That combination is where delays stop being technical and become organizational.
This is the third post in the Craft of Evolutionary Architecture series. Calyntro visualizes Complexity × Churn hotspots derived from your git history — including coupling context and contributor distribution. Explore the live demo against the full MongoDB open-source repository, no login required.
