The bug that's hard to see in review
Two developers (or two agents) implement features independently:
- Feature A: user authentication — writes to the
userstable on signup - Feature B: profile completion — also writes to the
userstable on first login
Neither feature is wrong in isolation. Together, they create a race condition on first login — two writes to the same record, potentially overwriting each other.
This kind of conflict is hard to catch in code review because the reviewer sees each PR in isolation. The overlap only becomes visible when you know what both features do to shared resources.
A feature registry makes overlap visible
The solution is a machine-readable map of what each feature touches:
{
"auth": {
"tables": ["users", "sessions"],
"routes": ["/api/auth/login", "/api/auth/signup"],
"permissions": ["users:write"]
},
"profile-completion": {
"tables": ["users", "profiles"],
"routes": ["/api/profile/complete"],
"permissions": ["users:write", "profiles:write"]
}
}
Before implementing any new feature, a conflict checker scans this registry for overlapping scope — same table, same route, same permission.
Five outcomes, not just pass/fail
When a conflict is detected, the resolution isn't binary. There are five options:
| Decision | Meaning |
|---|---|
| EXTEND | The overlap is compatible — both features can coexist without changes |
| MODIFY | One feature needs to adjust its scope to avoid the overlap |
| REPLACE | The two features should be merged into one |
| ISOLATE | Separate the data — give each feature its own table |
| ABORT | The new feature conflicts too deeply — do not proceed |
Forcing an explicit decision for each conflict is the point. The goal isn't to prevent all overlap — it's to prevent unexamined overlap.
Why this works better than hoping code review catches it
Code review happens after the code is written. Changing the data model at that point is expensive — you're rewriting logic, not adjusting a plan.
A conflict check before implementation means the conversation happens at the cheapest possible moment: when nothing has been built yet.
The registry also serves as documentation. Six months later, when someone wants to add a new feature that touches users, they can see exactly what already writes there and why.
The lightweight version
You don't need a script to get most of the value. A simple features.md file listing each feature's tables and routes, reviewed before any new feature starts, gives you 80% of the benefit with zero tooling overhead.
The script matters when you have enough features that manual scanning becomes unreliable — typically somewhere above 15–20 features touching shared resources.
The principle underneath
Every shared resource in your system is a potential conflict point. Making those resources explicit — naming them, listing who touches them — turns invisible conflicts into visible ones. Visible conflicts get resolved. Invisible ones ship to production.