A system does not become hard to evolve overnight. The degradation is gradual, and because it is gradual, it is tolerated longer than it should be. The team adapts. Estimates grow longer, but nobody knows exactly since when. Workarounds multiply, but each one in isolation seems reasonable. The system still runs, so the issue is never urgent enough to reach leadership.
The problem is that when it finally does, it is often too late for a gentle fix. The question is therefore not “do we have technical debt” (the answer is always yes), but: to what extent is this debt concretely slowing down the ability to deliver, secure and evolve the system?
Certain areas become untouchable
When a team starts saying “we’d rather avoid that module”, the signal is already there. Not necessarily because the component is highly complex in itself, but because it combines properties that make every intervention risky: low test coverage, tight coupling with other modules, historical logic that no one fully masters any more.
This phenomenon is often measurable. By cross-referencing code complexity with modification frequency in the Git history, you can identify hotspots: those files that are both complex and frequently changed, concentrating regression risk. A 2,000-line file that has not been touched in two years is not a priority. The same file modified 30 times in six months is a structural problem.
When three or four files concentrate both complexity and rate of change, it is no longer a code problem. It is an architecture problem.
Estimates become vague
A fragile system is also recognisable by the quality of its estimates. When a team struggles to say whether a change will take two days or three weeks, it is not a project management problem. It is a system readability problem.
A stable and predictable delivery lead time means the team understands the system and can anticipate the impact of a change. An erratic lead time, where seemingly similar tasks take sometimes one day and sometimes two weeks, signals that the system has opaque areas whose impact is unpredictable.
This vagueness never stays purely technical. It surfaces in the business first, as frustration about delivery timelines. Then in planning, when roadmap commitments become impossible to keep. Then with leadership, when the IT budget grows without delivery capacity following suit. The visible symptom is political, but the root cause is architectural.
Knowledge becomes concentrated
Another reliable indicator is dependency on a few individuals. If one or two people still know “how it really works”, the system holds. But it holds on a fragile foundation.
In concrete terms: when the majority of changes to a critical module come from a single developer, a sick leave, a departure or a holiday is enough to block the team. The difficulty is not just the code. It is the fact that the understanding of the system is no longer sufficiently shareable.
A module that only one person understands is often a module that the organisation has never needed to make shareable. This debt is not just technical; it is also organisational, and it is paid for eventually.
Security and compliance become disproportionate
On a well-structured system, integrating strong authentication takes a few days. Strengthening logging takes a week. Fixing a data exposure takes a few hours. On a poorly readable system, the same operations take weeks, sometimes months, because the existing codebase no longer provides clear footholds.
When the security team asks to add access control on an endpoint and the estimate comes back as “three weeks minimum, and we’re not sure about the impact on other flows”, the issue is no longer security. It is architecture. A healthy system remediates a critical vulnerability within days. When that timeline stretches to several weeks, or when certain fixes are classified as “too risky”, the system is in a state of active security debt.
For a compliance audit, the ability to document a data flow end-to-end is a good readability test. If this documentation requires questioning four different people and reading deployment scripts to reconstruct the path, the system is no longer efficiently auditable.
Workarounds proliferate
Competent teams always find ways to keep delivering. This is both a strength and a mask. The problem is not the occasional workaround; it is the point where the workaround becomes the normal way of operating.
Manual CSV export before reprocessing in a spreadsheet. Double entry between two subsystems that no longer communicate. A local script on a developer’s machine, never industrialised, that reconciles data every morning. A fix applied directly to the production database because the application deployment is too risky. A business rule implemented in an Excel file rather than in the system, because “it’s faster that way”.
Each of these workarounds, taken individually, is a pragmatic solution to a real problem. But their accumulation is a strong signal: the system no longer properly supports the business. And this divergence is rarely visible in monitoring dashboards — it is only discovered by talking to the people on the ground.
Responding early
When several of these signs compound, the first reflex is not to rewrite. The first reflex is to name the problem and make it visible.
Map the flows and dependencies. Identify the fragile areas. Pinpoint the modules that concentrate risk. Understand where workarounds are hiding. Estimate what maintaining the current state actually costs: additional development time, incident costs, opportunity cost of undelivered features.
It is this estimate that enables you to defend a modernisation budget to leadership, based on concrete data rather than a feeling of technical discomfort.
The diagnostic phase is rarely spectacular. It is almost always decisive.
Conclusion
A system that is hard to evolve is recognised less by its size than by its symptoms. Untouchable zones, fragile estimates, overly localised knowledge, costly security, recurring workarounds: when several of these signs compound, it is time to regain a clear reading of the system before claiming to transform it.
Identifying what blocks evolution before pretending to transform: these readings structure our engagements. Modernization and managed services for trust-critical systems.