Why Merge Conflicts became the new Agentic Bottleneck
Revisiting some techniques from Your Code as a Crime Scene in the light of agentic coding. Specifically, how a socio-technical fit becomes even more important now that agents are our actors.
One of the more surprising effects of agentic coding is that it reinforces the fundamentals of software engineering. The less we humans code ourselves, the more we need to optimize for design, architecture, and a socio-technical fit. Agents might not have minds, but coordinating multiple agents in the same codebase is non-trivial. It puts pressure on the software architecture.
A good example of that pressure is merge conflicts. Merge conflicts seem to have their heyday now. And teams are experiencing them at agentic speed.
Merge conflicts as a socio-technical signal
The reaction so far seems to be to double down on better PR tools. Stacked PRs, multi-queue systems for PRs, intelligent conflict resolution, and much, much more. It’s all interesting, but also clear that we’re patching symptoms, rather than fixing the root cause.
So, let me go out on a limb and claim that recurring merge conflicts are a sign of socio-technical problems. And it doesn’t matter that the social agent is an, well, agent.
Yes, the people organization plays a large part, too. Team boundaries, branching strategy (the less, the better...), and ownership all contribute. But the root cause is often technical. When that’s the case, no matter how you re-org, the fundamental problems stick. No org chart can dig you out of an architectural blob.
The secret to parallelizing work
As Fred Brooks pointed out in The Mythical Man-Month, software work stops scaling linearly once tasks depend on each other. Specifically, coordination work grows quadratically: the number of communication paths becomes n(n-1)/2, where n is the number of people involved. Work will stall, be it via merge conflicts, review bottlenecks, or — common in the past — “sync” meetings.
That works in reverse, too. Development work can - and should - be parallelized when it represents independent tasks with similar relevance and urgency. However, to be effectively parallelizable, those tasks typically have to be independent at the level of the problem domain.
How software architecture supports development work
And that’s where architecture comes in: that independence has to exist in the code, too. This means aligning the code with concepts from the problem domain: separate features, workflows, or product capabilities also need separate homes in the solution design. Otherwise, chances are that two seemingly independent tasks end up touching the same part of the code.
Recurring merge conflicts are the canary telling you that there is a misalignment between a) the work you do, and b) the type of work your architecture supports.
We only need to look at the leaked Claude Code repo to see the problem. Look at virtually any interesting part, and you’ll see how behavior seemed to converge in the same places.
The preceding extractToolStats() is a perfect example of architectural convergence. Git analytics, diff calculations, telemetry, UX timing analysis, and more, all accumulate in the same orchestration flow.
This means unrelated changes inevitably collide in the same function, simply because the poor modularity gives many reasons for agents to touch not only the same file, but even the same function. Under those conditions, it’s no wonder that we run into merge conflicts.
An old problem in agentic clothes
Fair enough, this type of misalignment is not a new problem, either. If you scaled up a human team on top of the same architecture, you would run into the same coordination pain, as experienced by countless projects ignorant of Brooks’s Law. The difference is speed. When it comes to merge conflicts, GenAI truly delivered on the 10x promise.
That is also where behavioral code analysis becomes interesting. If the same areas of the codebase keep attracting parallel work, recurring merge conflicts are a signal. They tell you where the boundaries in the code no longer support the work being done. The structure of the codebase might still look sound at a quick glance, but your change patterns tell a different story.
Shine a light on coordination costs in the code
Behavioral code analysis to the rescue; it reveals where parallel work repeatedly converges.
Hotspots show where the system attracts change pressure.
Coordination analysis reveals where many contributors compete for the same areas.
Change coupling exposes architectural boundaries that fail to support independent evolution.
Together, those analyses make coordination costs in code visible.

Acting on behavioral data
A behavioral code analysis won’t tell you what to do. It’s evidence and priorities, leaving the resolution to you. Depending on what the analysis reveals, those next steps might be more or less painful.
Examples include:
Heavy author congestion in a hotspot: Frequently, the root cause is technical. Lack of modularity, low local cohesion, with too many business responsibilities squeezed into the same module. When that’s the case, break the hotspot apart along domain boundaries.
Change coupling in a local cluster: A typical sign of low package cohesion. Here, the solution might be to combine code spaced out in various files into the same unit and/or package.
Change coupling across distinct architectural elements: This is a bad one. It usually indicates erroneous architectural boundaries, with the most common cause being a technical separation of concerns (thin: MVC or MVP style patterns), rather than a system where the building blocks communicate domain concepts.
Granted, none of those fixes are quick. But absolutely necessary. Otherwise we’ll keep grasping for tools that can relieve symptoms while the disease keeps spreading. When that happens, those parallel agents are no longer delivering value faster. Instead, there’s a serial bottleneck in the system, and it becomes the limiting factor.
References
The behavioral code analysis techniques are captured and described in:


