In March 2023, Amazon.com published an article on how it rearchitected its Prime Video offering from a distributed microservices architecture to a ‘monolithic’ architecture running within a single Amazon Elastic Container Service (ECS) stack.
Despite a reduction in infrastructure cost of over 90%, the seemingly counterintuitive move generated consternation across the cloud architecture community. Monoliths are ‘bad,’ laden with technical debt, while microservices are ‘good,’ free from such debt, they trumpeted. How could Amazon make such a contrarian move?
This controversy centers on what people mean by ‘monolith,’ and why its connotation is so negative. In general parlance, a monolith is a pattern saddled with architectural debt – debt that the organization must pay back sooner or later. Based on this definition, an organization would be crazy to move from an architecture with less debt to one with more.
But as the Amazon story shows, there is more to this story – not only a clearer idea of the true nature of architectural monoliths, but also the fundamental concept of architectural debt.
Architectural Debt: A Particular Kind of Technical Debt
As I explained in an earlier article, technical debt represents some kind of technology mess that someone has to clean up. In many cases, technical debt results from poorly written code, but more often than not, is more a result of evolving requirements that existing technology simply cannot keep up with.
Architectural debt is a special kind of technical debt that indicates expedient, poorly constructed, or obsolete architecture.
Even more so than the more familiar source code-related technical debt, architectural debt is often a necessary and desirable characteristic of the software architecture. The reason: too much software architecture in the early phases of a software project can cause systemic problems for the initiative that lead to increased costs and a greater chance of project failure.
In fact, the problem of architecture that is too much and too early, aka ‘overdesign,’ is one of the primary weaknesses of the waterfall methodology.
Instead, modern software principles call for ‘just enough’ or ‘just in time’ architecture, expecting architects to spend the minimum time on the task necessary to guide the software effort. If a future iteration calls for more or different architecture, then the architect should perform the additional work at that time.
Good vs. Bad Architectural Debt
Given such principles, you’d think that Amazon’s move to a monolith would be better received.
After all, the reason Amazon’s architects chose microservices in the first place was because such a decision was expedient and didn’t require excessive architectural work. The move to a monolith was simply a necessary rearchitecture step in a subsequent iteration.
Where the confusion arose was over the difference between this ‘good’ type of architectural debt – intentional ‘just enough, just in time’ architecture as part of an iterative design – and the ‘bad’ type: older, legacy architectures that may have served their purpose at the time, but are now obsolete, leading to increased costs and limited flexibility.
Examples of Good vs. Bad Architectural Debt
It may be difficult to distinguish between the two types of architectural debt. To help clarify the differences, here are two examples.
Example #1: Addressing good architectural debt.
An organization is implementing an application which will eventually have a global user base. The architects consider whether to architect it to support internationalization but decide to put this task off in the interests of expediency.
Eventually the development team must rework the app to support internationalization – a task that takes longer than it would have had they architected the app to support it initially.
Nevertheless, the organization was able to put the application into production more quickly than if they had taken the time to internationalize it, thus bringing in revenue sooner and giving themselves more opportunity to figure out how they should improve the application.
Example #2: Addressing bad architectural debt.
An organization struggles with the limitations of its fifteen-year-old Java EE application, running on premises on, say, Oracle WebLogic. The app is now too inflexible to meet current business needs, and the organization would like to move the functionality to the cloud – a migration that WebLogic is poorly suited for.
The organization must first take inventory of their existing architecture, requiring architectural observability that can delineate the as-is architecture of the application, how it’s behaving in production, and what its most urgent problems are. The architecture team must also establish an architectural baseline and then determine how much the as-is architecture has drifted from it.
At that point, the organization must implement a modernization strategy that considers the technical debt inherent in the internal interdependencies among architectural elements (Java classes, objects, and methods in this case). Only then can it make informed modernization decisions for the overall architecture as well as the software components that make up the application.
Architectural observability from tools like the vFunction Continuous Modernization Manager is essential for understanding and thus dealing with bad architectural debt. Such debt is difficult to identify and even more difficult to fix. In some cases, fixing architectural debt isn’t worth the trouble – but without architectural observability, you’ll never know which architectural debt you should address.
The Intellyx Take
The term ‘monolith’ is saddled with all the negative connotations of bad architectural debt, but as the Amazon example illustrates, such connotation paints the term with too wide a brush.
In reality, what constitutes a monolith has changed over time. Object-oriented techniques relegated procedural programs to the status of monolith. Today, cloud native architectures apply the label to the object-oriented applications of the Java EE days.
Understanding architectural debt, therefore, goes well beyond the labels people put on their architectures. With the proper visibility, architects can differentiate between good and bad architectural debt and thus begin the difficult but often necessary process of modernization in order to get a handle on their organization’s architectural debt.
Copyright © Intellyx LLC. vFunction is an Intellyx customer. None of the other organizations mentioned in this article is an Intellyx customer. Intellyx retains final editorial control of this article. No AI was used in the production of this article.
Image credit: Atom.D.