Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Categories of Monoliths

Categories of Monoliths

This item in japanese

We've had lots of articles on microservices over the past year or more, if we include looks at various anti-patterns, as well as their relationship to monoliths and things to look out for when moving towards a microservices architecture. Although some developers start from a greenfield/blank sheet of paper when building applications with microservices, many are looking to use them to help decompose their legacy monolithic applications. We've had people give their experiences in this regard in the past, but recently Derek C. Ashmore has looked at categorising monoliths with a view to then, in a subsequent article, discussing how to break them into more management components which could, presumably, be implemented as microservices.

A monolith is an application that has grown too large to effectively manage. That is, it's expensive to enhance and fix. Change to monoliths often come with unintended consequences; you fix something and other things break. Monoliths effectively marry you to a technical stack, making it difficult to grow with new technologies as they evolve and mature. Due to the size and complexity of underlying monolithic code, it's often expensive and time-consuming to bring on new developers (there's so much to learn). The same labor characteristic limits the business in that outsourcing change often isn't an option.

So let's look at the categories Ashmore has identified, and he notes characteristics of them may be shared across a single monolithic application. He starts with the "Feature-Bloated Web Application":

This type of monolith is specific to web applications. It becomes larger and more complex as new features are added. Moreover, some of those new features weren't considered when the application was originally designed. Consequently, those new features are often inelegantly "tacked on" and don't really conform to the initial design of the application. Often, there's no time and budget to revamp the application design to add new features in ways that are easy to maintain and support. The consequence for this is often technical debt in the form of unwanted coupling.

Under this category Ashmore mentions various common causes and effects, such as the fact that adding new features can increase complexity across the entire application:

New features impact not only the user interface but server-side backing code that supports that interface and the underlying database. Often that server-side backing code and database is tightly coupled with the user interface and "assumes" that the business processes currently implemented by the interface.

As well as that most monolithic applications do not measure or track the usage of specific features:

As a consequence, features, once implemented, never get removed. It would be logical to remove features that aren't used or aren't used often as the complexity for having that code remain will negatively impact your ability to add new features down the road. Sadly, getting budget for removing features is hard to do in most organizations as the benefit to doing so is hard to measure and too intangible.

The next type of monolith is the "Data Store Strangle":

Despite the length of time that databases (relational and non-relational) have existed, database design skills are woefully inadequate at most organizations. As a result, you often get a process-oriented database structure. That is, a database structure that is specific to processes currently implemented by the application that database supports.

We've already heard recently from Christian Posta that data is the hard part of working with microservices and Ashmore concurs that it is also one of the driving forces behind monoliths and breaking them apart. As he says, refactoring the database can be harder and more time-consuming than refactoring the application code:

Any database refactoring often must take place while supporting existing code. Also, any database refactoring also must have some type of data conversion as a part of it.  Another way to look at it is that code only has state that's transient. That is, its state exists only at run time. Database state is persistent. Changes to that database must include converting the data that was stored into its new format.

And in Ashmore's experience, refactoring databases can be riskier than refactoring code typically due to the complexity of backing out the refactored database if it is found to have been done incorrectly and at the same time not losing any new data that was entered since the refactor took place. In most organisations losing data is not an option that can be considered.

Ashmore's final category is the "Over-Engineered Tarball Component", which he puts down to developers getting "bored and looking for something more interesting to do" than just that which is necessary to accomplish the task at hand. This leads to a knock-on effect that if the original developer leaves, maintaining the code becomes more difficult due to the fact the additional complexity may well have only been understood (and documented) in the head of that developer.

These are Ashmore's categories of monoliths, which he has come across to date. In a future blog posting he intends to show how they can be broken down into more manageable components or applications. When the time comes we'll try and post a follow-up article here.

Rate this Article