Scaling Monolithic Applications

Nader Medhat
The Startup
Published in
5 min readFeb 5, 2021

--

What is a Monolithic application?

Monolithic applications are designed to handle multiple related tasks. They’re typically complex applications that encompass several tightly coupled functions.

For example, consider a monolithic eCommerce SaaS application. It might contain a web server, a load balancer, a catalog service that services up product images, an ordering system, a payment function, and a shipping component.

As you can imagine, given their broad scope, monolithic tools tend to have huge codebases. Making a small change in a single function can require compiling and testing the entire platform, which goes against the agile approach today’s developer's favor.

The Advantages of using monoliths

Monolithic applications are a natural way for an application to evolve. Most applications start out with a single objective or a small number of related objectives. Over time, features are added to the application to support business needs.

The most obvious place to put new functionality is in the existing application. There are several reasons for this:

Communication costs

The cost of communicating components is near zero when the code is in the same application stack. Meaning, developers do not need to think about, or code around, things like networks and availability.

Reusability

If the problem is similar, code from existing applications can be reused with little effort. Code reuse at this scale is a natural thing to do when developing and can decrease time-to-market for application features.

Effort

Starting new applications has always involved significant effort. You must create a new artifact with all the configuration, all the build scripting, and tooling, and an entirely new set of hardware and network configuration (sometimes, a herculean effort). To make it more complex, code reuse is now more complicated across projects.

Monolithic applications provide teams with a single source code tree to work from. All changes accessible by any part of the application, allowing for single teams to work closely on the application. In server-side applications, monoliths have been, and continue to be, the standard for the last 20 years. So, why is a change necessary?

Problems with monoliths

Fault tolerance

Monolithic applications have high module interdependency as they are tightly coupled. The different modules utilize functionality in such an intro module manner that even a single module failure brings the system down due to the cascading effect, which is very similar to dominoes falling. We all know that a user not getting results for a product search would be far less severe than the entire system coming down to its knees

Scaling

Factors such as availability of different means of communication, easy access to information, and open-world markets are resulting in businesses growing rapidly and diversifying at the same time. With this rapid growth of the business, there is an ever-increasing need to accommodate an increasing client base. Scaling is one of the biggest challenges that any business faces while trying to cater to an increased user base.

Scalability is nothing but the capability of a system/program to handle the growth of work better. In other words, scalability is the ability of a system/program to scale.

Before starting the next section, let’s discuss and understand scaling in detail, as this will be an integral part of our exercise as we work on transitioning from monolithic to microservices.

The scalability of a system is its capability to handle an increasing/increased load of work. There are two main strategies or types of scalability in which we can scale our application.

Modularity

In respect to our monolithic application, where we may have an Order module, a change in the module Orders affects the module Stock and so on. It is the absence of modularity that has resulted in such a condition.

This also means that we can’t reuse the functionality of a module within another module. The code is not decomposed into structured pieces, which could be reused to save time and effort. There is no segregation within the code modules, and hence, no common code is available

Big database

Our current application has a mammoth database containing a single schema with plenty of indexes. This structure poses a challenging job when it comes down to fine-tuning the performance

Whenever deployment is planned, the team will have to look closely at every database change. This again is a time-consuming exercise and many times would turn out to be even more complex than the build and deployment exercise itself

Scaling a Monolith

Vertical Scaling

Usually, the obvious solution for scaling is to scale-up (vertical). This generally means increasing resources. Increasing CPU, Memory, Network, Storage, etc, for higher performance, allows you to perform more work and handle more load.

Horizontal Scaling

Scale-out (horizontal) scaling is distributing the workload over many resources. Loosely coupled systems allow you to distribute the system over different resources and provide better availability.

Using load balancers

Requests are handled by a load balancer, which then distributes the requests to the application. There are a variety of ways a load balancer distributes requests, the most common being Round Robin.

With a loosely coupled monolith, because we have very defined boundaries, this allows you to scale even further. You can start scaling the individual boundaries.

Split the codebase into several boundaries

However, we can create load balancing rules to create groups of servers that will only handle requests for a specific boundary. These are often called Target Groups.

With well-defined boundaries, you can decide how to scale and route traffic with a load balancer to a target-group that handles that boundary. Although each server has all the code in our monolith, it is really only using the boundary that it’s handling. All other boundaries are basically dead code.

Database

The database can also become a bottleneck in a monolith. But just as you can scale by the boundary on the application/hosting layer, you can also make these same types of scaling decisions at the database layer of the topology.

If one boundary has to handle more load, you could scale each database vertically differently. In the example above, DB1 might have more resources (CPU, Memory, etc) than the others.

Or you may choose to scale horizontally at the database level by adding read replicas or a cluster

Conclusion

at the end of this article, those are some resources for reading and getting more knowledge

Scaling a Monolith Horizontally (code opinion)

Are monolithic software applications doomed for extinction?

Monolithic applications (Microsoft)

--

--

Nader Medhat
The Startup

love reading , learning , writing and sharing