Recently we’ve had a number of clients ask us how to evolve a monolithic application into something better. In software terminology, a monolith is a single deployable unit of software that runs on a very specific set of infrastructure. As a result they tend to have infrequent release cycles and are subject to outages caused by infrastructure failure. A more modern approach to architecture usually involves smaller deployable units, multiple sources of data, and a flexible infrastructure like those found in public and private clouds.
When we peel back the covers, the business drivers for evolving a monolith are usually better agility, improved stability, speed to market, and IT operational efficiency. Just like the old saying, “How do you eat an elephant? One bite at a time,” attacking the monolith must be an incremental process of targeted changes over time. I thought it would be helpful to lay out a practical, step-by-step approach to moving the monolith.
But first, let’s describe what a monolithic application is and discuss when it is appropriate to move one. (Spoiler alert: Sometimes it is better to keep the monolith around.)
Monolithic applications come in different shapes, sizes, languages, and platforms. However they all exhibit some common characteristics:
Requires a specific infrastructure.
Monoliths are just as much about infrastructure as they are about code. Monoliths require a very specific infrastructure to run – a particular application server like WebSphere, databases, and other resources located in certain places, and they expect that infrastructure to always be available. When infrastructure goes away it causes a ripple effect that may bring down the entire system.
__Data is housed in a centralized database.
__A corollary to characteristic #1, monoliths read and write data from a centralized database or a small number of databases. Even if code is modular and well organized, “the centralized database becomes a massive coupling mechanism. Every single thing in an entire system is locked together because each component must use the database to manage state.” (Source: highscalability.com).
__Delivered as a single deployable unit.
__Source code is usually housed together and always delivered as a single deployable unit. Any change results in redeployment of the entire application to the target environment. The size of the code base is an important factor in determining if you have a monolith. A small- to medium-sized single code base is usually much easier to deal with than a lot of tiny ones. If your app is relatively small, like most startups and new products are, you can save yourself a lot of hassle by having a single, modular, well-organized code base. Monoliths, by contrast, are large and unwieldy.
__Combined front-end and back-end code.
__A monolith’s front-end code is packaged along with the back-end code, often using a server-side scripting technology such as Active Server Pages (ASP), Java Server Pages (JSP), or ColdFusion. If your code base contains both front-end templates and the back-end logic used to populate them, then you may be dealing with a monolith.
__Lacks substantial automated testing.
__This characteristic is optional but very likely to be present. Since most monoliths evolve over a long period of time, their testing approach is inconsistent at best and often non-existent. Unit and integration tests may have been removed or commented out at some point in the past or simply never written. This makes it particularly difficult for developers to make changes with confidence, and the risk of regression bugs or unintended side effects increases dramatically and slows delivery velocity.
Is all of this really so bad? Should you consider breaking up the monolith? To correctly answer these questions it is important to clearly define your goals:
Do you need to release small changes frequently?
Do you have very high uptime requirements for all or some of your app’s functions?
Does your app have usage or availability “hot spots” that could benefit from their own compute or storage resources?
Does your user interface change more frequently than your back-end logic?
Do you need to build mobile apps or expose your business to the outside world via APIs?
If you answered yes to some or all of these questions then you should consider moving all or part of the monolith. If not, you need to carefully consider your next steps. Distributed computing is hard and moving to a more distributed architecture is going to cost your organization real money. Do the benefits of moving the monolith outweigh the costs?
Groupon had some of these goals in mind when they decided to move the monolith. Groupon’s business hit an inflection point after several years of growth by acquisition and expansion into new international markets. Mobile first was a key driver for their decision. Before the inflection point, they decided that keeping their monoliths around was the best way to quickly grow the business.
Over the next few weeks we are going to lay out a multi-step approach to this journey, and your answers to the goal questions above will help inform the route you take to the destination. The good news is it’s not an all or nothing trip – if your release cycle time decreases by 20%, uptime improves by 2%, and stakeholders are happy after step one, congratulations! Move on to something more important and continue the journey when your business hits an inflection point.
We would love to hear about your experiences along the way.