What software architecture approach should you use? A comparison of monoliths and microservices

Software developers are always on the lookout for new and more effective ways to build applications. Advancements come in various forms including programming language updates, hardware upgrades and new technology releases, but also the approach to software development itself. For example, in recent years, developers have been investigating new ways to organise a software system's architecture, which describes how the system's resources are organised. Traditionally, most software systems adopted a monolithic architecture, wherein the entire system was bundled in a single unit; however, an alternative architecture approach called microservices is receiving more and more attention. In brief, the microservices approach involves dividing the system into dedicated modules, each with a bespoke purpose and technology stack. Microservice modules can communicate with one another via application programming interfaces (APIs) but are largely able to complete tasks independently. In this way, microservices allow developers to build applications that are scalable, resilient, and adaptable to different user needs. While monolith systems can be a cost-effective and sufficient solution for small applications, their lack of flexibility can make it difficult to upgrade and expand the system. For this reason, growing organisations often seek to convert their monolith applications into microservices. In this tutorial, we will explore and compare the monolithic and microservices-based software architecture approaches and discuss how they can be used to build effective systems.

monolith-microservices-architecture.png

What is a monolithic system?

A monolithic software system comprises a single unit containing all the technology and resources required to run the application. For example, a monolithic application will often feature a database to store the application’s data, a client-side interface that displays content to the user, and a server-side application that powers system processes. Many well-known companies started out using monoliths, including Netflix, Spotify, Twitter, and Amazon. A primary reason for using monolithic systems is their simplicity. For many new companies, complex multi-component systems are not necessary, and a single unit is sufficient to handle all the business’s needs. All the source code for a monolithic system is stored in a single place, so development, testing and deployment are relatively straightforward. Keeping things simple at the early stages of a business is advantageous for proving that the software solution is feasible and effective while keeping costs low and minimising the complexity of the system. As the business grows, however, monolithic systems can encounter challenges including difficulty meeting increased demand, outdated technology, and problems rolling out new features and upgrades. For this reason, established businesses may consider converting their monolithic systems to microservices instead.

What are microservices?

In contrast to monolithic systems, the microservices software architecture approach seeks to compartmentalise the system into separate units. Each microservice unit has a specialist role within the larger system and a bespoke technology stack to fulfil this role. If a microservice requires a database, then that database will often be inaccessible to other microservices in the system. Each microservice should be capable of completing its tasks independently; however, microservices can communicate with each other via application programming interfaces (APIs) if needed. In a business environment, it is common for each microservice to be managed by a different team. While microservices may require greater costs and resources to set up and maintain than a monolithic system, these expenses are often worthwhile for larger systems because of the flexibility, scalability, and resilience that microservices offer. For example, if a microservice is damaged, other services should be largely unaffected. In contrast, if a monolith is damaged then the whole system could crash. A comparison of the benefits and drawbacks of the monolithic and microservices-based approaches is integral to deciding on the optimal software system architecture approach.

Comparing monolithic and microservices-based systems

The monolithic and microservices-based architecture approaches have advantages and disadvantages that should be considered when designing software systems. For example, monolithic systems are typically more straightforward to develop, test, deploy and maintain because monolithic applications comprise a single unit. Meanwhile, microservices offer greater flexibility than monolithic applications. Each microservice unit can use bespoke technology that is tailored to its purpose. Also, microservices can be developed by dedicated teams and deployed on different timeframes as required. A more comprehensive overview of the benefits of monolithic and microservices-based systems is provided in the below table.

The advantages of monolithic and microservices-based software system architecture approaches
Monoliths Microservices
Monoliths are often simpler than microservices. It is more straightforward to design, develop, test, deploy and monitor a monolithic system. Microservices are resilient. If one service fails, other services should be able to continue to operate unaffected. Problematic updates can also be rolled back relatively easily.
The entire system can be deployed in a single unit, such as a JAR file. Microservices are scalable. You can scale up, by increasing the hardware resources such as RAM, or scale out, by adding more machines to your system.
Response times for a monolith system are often fast because processes are performed locally and do not require involvement from other services. Each microservice unit can be equipped with a unique technology stack that is best suited to its speciality and purpose.
It is easy to onboard new team members because the source code for monolithic systems is stored in one place. There are fewer obstacles to changing service providers for microservice units compared to a larger monolithic system.
User authentication is simple because the user only needs to log into one service rather than multiple. Microservices-based architecture can improve productivity. For example, teams can work on multiple parts of the system simultaneously.

The monolithic and microservices-based architecture approaches are not without their drawbacks. For example, monolithic systems are notoriously difficult to scale. If you want to upgrade a monolithic application, then you must upgrade the entire system. It is not possible to upgrade just part of a monolithic application. Furthermore, even if you do successfully scale a monolith system, you will likely find the system becomes increasingly complex and challenging to maintain. While microservices-based systems are easier to scale and upgrade, coordinating the development, testing, deployment, and maintenance of multiple units requires lots of resources, expertise and time. Also, if communication between microservice units breaks down, there could be slow response times or even a chain of failure if the system is poorly designed. A chain of failure describes how the breakdown of one service can cause the failure of other services also. A detailed comparison of the disadvantages of monolithic and microservices-based systems is provided in the below table.

The disadvantages of monolithic and microservices-based software system architecture approaches
Monoliths Microservices
Users of a monolithic application may have access to more features than they need. The ability to scale up a microservices-based system by increasing hardware capacities (e.g. RAM) is limited by the motherboard and operating system capabilities.
Monoliths are particularly vulnerable to large data breaches and hacks because most data is stored in one place. It can be complex to coordinate user authentication across multiple services.
A problem or bug could compromise the entire system. You must guarantee the security of multiple services.
Scalability is limited and costly. You must scale the entire system and not individual parts. Even if you can successfully scale a monolith system, the monolith will become increasingly complex and harder to maintain. Network calls between services may fail and cause delays.
Technology suppliers are often reluctant to take on monoliths, which can restrict your ability to change service providers. A system comprising lots of microservices can be complex to develop, test, deploy and maintain.
Parts of the monolith may become outdated quickly because of the challenges with rolling out upgrades. For example, you could find yourself stuck with an old version of Java and be unable to transition to a new version. Externalised processes such as configuration, logging, metrics and health checks can create cross-cutting concerns. Cross-cutting describes the dependency of one part of the system on another.
It is difficult to have multiple teams working on a monolithic application because the boundaries between sections are unclear; the work of one development team may impact the work of another.

Transitioning from a monolithic system to microservices

New businesses often first design systems as monoliths because of the simplicity offered by the monolithic architecture approach. As the business grows, however, the scalability and flexibility offered by microservices often become more and more appealing. So how would you approach the transition from a monolithic system to a microservices-based system? First, you should look to gain a thorough understanding of your business’s needs and requirements. Each requirement should have clear boundaries because it is likely that each requirement will be fulfilled by a dedicated microservice; however, sometimes it is acceptable to integrate similar requirements into a single unit. For instance, it is important to avoid creating inefficient and complicated microservices, as idle services can be costly to maintain. Altogether, you should aim to divide the monolith into multiple services with clear boundaries that can expect sufficient traffic to justify their operating requirements.

Once you have a clear view of the required microservices, you should decide on the appropriate technology stack that is best suited for each unit. For example, how will you store data? Typically, each microservice will use one data source and table. If you find yourself considering multiple data sources for a single service, then it is possible the service is overly complex and may benefit from being split into multiple services. Also, you should consider what programming languages and technological resources each service will require to fulfil its responsibilities. A key benefit of the microservices-based approach is that each module can use a bespoke technology stack, so you are encouraged to explore what the best solution is on a service-by-service basis. However, remember to ensure that the costs, expertise and resources required to implement and maintain your chosen technology are feasible.

Finally, you may like to explore methodologies that can facilitate the efficient development of your microservices. For example, many organisations implement the Agile software development methodology, which emphasises the frequent delivery of new versions of the application and prioritises the incorporation of user feedback. Also, to facilitate the development of multiple concurrent services, teams often incorporate a continuous integration approach. Continuous integration involves a predefined set of automated build and testing steps that are followed each time an update is released by the development team. The automated build and test steps ensure each new release fulfils its intended requirements, and also that existing features continue to operate as expected.

Example case study: Transitioning a monolithic online store to microservices

Throughout this tutorial series on microservices and Spring Boot, we will follow an example case study of an online business to illustrate key concepts and principles. In the example, we will put ourselves in the shoes of an imaginary record label called CG Records (Coders' Guidebook Records). CG Records has signed several artists and makes money by selling music. Initially, CG Records sold music in physical formats such as vinyl records, CDs, and cassette tapes; however, the record label is looking to offer streaming and digital downloads to appeal to a modern audience. Currently, CG Records distributes its products using a monolithic online store: the product catalogue, order pipeline and delivery management system are all coordinated using a single application.

Going forward, CG Records is looking to transition from its monolithic application to a microservices-based system. Their reasoning is three-fold. First, CG Records is looking to expand its business and offer new services such as streaming and digital downloads. CG Records also wants the opportunity to easily add new features as the business grows. Second, CG Records is looking for a better-performing system. Currently, the monolithic application struggles to handle client requests and sometimes crashes during periods of high traffic, such as when an artist releases a new record. Finally, CG Records wants to upgrade elements of the technology stack. Some aspects of the monolithic application are outdated but the legacy code is so embedded in the overall system that is not feasible to upgrade to better performing resources.

After careful consideration of the business’s requirements and functions, a plan was drawn up to split the monolithic application into several microservices handling the product catalogue, payments and orders flow, user account management, and delivery management platform, respectively. Each microservice has clear boundaries and addresses a different business requirement. In splitting the monolith into microservices, we can ensure each service has the technology, security and profile configuration required to fulfil its responsibilities. Once all the existing monolith functionality has been transferred to microservices, we can incorporate additional services to handle the streaming and digital download functionality and any other new features that the business requires. In upcoming tutorials, we will explore further how to create microservices, handle business processes, and facilitate communication between microservice modules using APIs.

converting-monolith-to-microservices.png

<<< Previous

Next >>>