When building a software system, engineers recognize three fundamental truths:
- All software has an architecture, whether it is designed and implemented intentionally, or it emerges by coincidence.
- System complexity grows over time as requirements shift, use cases evolve, team members come and go, and technologies advance.
- Without deliberate management of the system’s evolution, its architecture may stray from its original objectives and blueprint, leading to unintended architectural drift.
Architectural drift can affect any application, irrespective of its initial architectural style or the quality of its original design.
After all, the ease of making changes to a system has significantly increased compared to the past. Gone are the days when you had to phone your hardware rep to order a new server, confirm that there was rack space for it in the data center (i.e. basement), configure it, integrate it into the network, and migrate data into it. Nowadays, a few clicks in a cloud vendor console or a commit to Infrastructure as Code (IaC) can redefine your application’s architecture in mere minutes.
Engineers not only face the challenge of adapting to continuously evolving system architectures but also grapple with the shifting role of software architecture within agile teams and the lack of visibility into the architectural decisions made by other teams.
This leads to a vicious cycle where architectural drift makes the system increasingly difficult to comprehend and modify. Developers find it challenging to implement changes without causing unintended side effects or disrupting existing functionalities, which leads to further architectural drift.
As a result, development cycles lengthen, costs rise, and overall productivity declines.
Understanding the root causes, consequences, and strategies for managing system architecture drift is vital. This blog post aims to provide a comprehensive exploration of architectural drift, including its definition, underlying causes, consequences, and effective mitigation techniques.
The What and Why of System Architecture Drift
System architecture drift falls under the broader category of Architectural Technical Debt, which encompasses all the intentional and unintentional decisions made during the system design process (e.g. architectural style, tech stack, development methodologies, etc.), that result in issues such as reduced maintainability, increased complexity, decreased performance, and scalability challenges.
Specifically, Architectural Drift refers to the gradual deviation of a system’s architectural design from its original or intended architecture due to ad-hoc alterations and additions.
Imagine that you’re building a house designed in the Mediterranean style, complete with characteristic clay tile roofing, stucco walls, and wrought iron balconies. Suppose, partway through, you decide to incorporate a Gothic-style round turret to accommodate your astronomy hobby. Later, to cater to your growing family, you might add a post-modern extension. What began as a cohesive design evolves into a disjointed amalgamation of styles.
This analogy mirrors the reality in software architecture: the system may start with a clean architecture but evolve into a complex tangle of multiple architectural paradigms, inconsistent coding practices, redundant components, and tangled dependencies due to uncoordinated additions and modifications.
There are various reasons behind system architecture drift:
Adapting to Evolving Needs: Architectural adaptations are often intentionally made to align with changing requirements or evolving business needs. Software systems are dynamic entities, and architectural drift can sometimes reflect an organization’s commitment to rapidly delivering new functionalities, meeting customer demands.
Unclear Architectural Governance: Development teams lack a defined architecture, guidelines, or principles to guide their work. This lack of direction can lead to ad-hoc decision-making and improvisation, contributing to architectural drift.
Result of Architectural Technical Debt. Compromises, shortcuts, and errors made during development can have a knock-on effect on other architectural decisions. Examples of ADT issues that influence future choices:
- Re-inventing the Wheel: Choosing custom-built components over existing solutions with similar functionality (e.g. building your own persistence library).
- Permanent MVPs. A temporary, “bare-bones” solution becoming an integral part of the system’s architectural foundation (e.g. adopting prototypes of a new architecture, immature R&D components, experimental development branches, etc.).
- Persistent Workarounds. A temporary workaround, implemented to bypass some architectural constraints, becoming deeply embedded into the architecture.
Inadequate Collaboration. Poor collaboration within and between teams can exacerbate architectural drift. Without a shared understanding or visibility into the overall system architecture and modifications made by other teams, disjointed efforts can lead to increased fragmentation and inconsistency in the system’s architecture.
Architectural drift ultimately builds over time due to a multitude of factors — different business needs, architectural directions, rogue spinoffs — resulting in increased system complexity and creating a less maintainable and cohesive architecture.
What's Next
For more about system architecture drift check out these next articles:
- 101 on Architectural Technical Debt
- [Part 2] Architectural Drift in Real Life Systems
- [Part 3] The Temptation to Ignore Architecture Drift
- [Part 4] Effective Measures to Control System Architecture Drift
Thank you for reading! 💜
Top comments (8)
System architecture is the result of bad experience. With every project your experience grows, so it is no wonder architecture is evolving.
For a young developer with very little experience, the shifts will probably be larger than for an experienced one. But some day you may find, that times have changed and your "do it again, Sam"-experience is not useful anymore. Then it is time to go shifting...
Good point. The experience of the engineering team building the system is a factor (among the others) that affects the degree to which they will experience drift.
But I also think that it's very difficult to account for every future requirement, technology shift, etc. and so system evolution is inevitable regardless of experience. 😊
Completely agree - sometimes this can even be architectural infeasibility, when skillsets or culture are not up to the planned solution design, and something needs to give.
One technique that can help is to use architecture decision records. You can even start using them to record previous decisions - @tekiegirl wrote about that recently. User stories and other written up collaborative techniques can help too, but tend to focus on the user-visible aspects, as opposed to why and and what for from the system's perspective. They can improve the decision due to consultation and discussion but are a poor place to store your architectural designs!
That's a great comment - I'm a huge fan of ADRs! Recording why you took a specific system decision and what trade offs you considered (and accepted) is critical when looking to evolve the system.
However, I think ADRs are affected by similar issues that Docs suffer from: they are not always systematically created during the development process, they are mostly manually, potentially fragmented across multiple sources and require lots of maintenance. That's all to say, that alone they don't solve the underlying problem 😊
Good article, thank you.
Thank you for checking it out!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.