In the previous post, we analysed different architectures used by developers to create web applications. So far, though, we have only discussed web applications from a micro perspective. If we zoom out and look at them as a whole, we see that the architecture of a web application can be divided into several functioning models, depending on how the source code is organised and distributed across servers.
Note
Both the architectures from the previous posts and those from this one can be categorised as web architectures. However, to easily differentiate them, let’s set a convention.
Multi-page architecture |
Single-page architecture |
Widget app architecture |
-> these are architecture types
Monolith architecture |
Microservices architecture |
-> these are architecture models
Monolithic architecture
1: a single great stone often in the form of an obelisk or column
// A granite monolith stands at the center of the park.
2: a massive structure
// The 70-story monolith is one of Europe’s tallest buildings.
— Definition by Merriam-Webster
From ancient times, humankind used the word “monolith” to describe a huge, single block of stone. The same word is used nowadays by software engineers to describe a web application that has all its code organised into a single and indivisible unit. Usually, a monolithic web application consists of the UI, a database, and a server-side application. All these components are managed together in the same codebase, as shown in Figure 1.
The architecture of the above application can be illustrated as in Figure 2.
However, just because in a monolithic application the entire logic is self-contained in a single project doesn’t mean its code devolves into Spaghetti Code. Most monolithic applications are actually very well organised and follow code organisation patterns like model-view-controller (MVC) or model-view-viewmodel (MVVM).
The problem with monolithic architecture
This paradigm has been the de-facto architecture model for countless applications, and it’s still used by many for good reasons:
- For small projects, monolithic architecture considerably speeds up the application deployment phase as the team doesn’t have to deal with the complexity of deploying multiple servers and containers. In this case, the deployment can be as easy as copying the application code to the server.
- Starting a new project is easier, and for this reason, startups use a monolithic architecture for their MVP applications.
But here is the main downside of the monolithic architecture: it is hard to scale.
Once an application starts to grow and hosts more and more users, the complexity will increase, as well as the number of files and folders. At some point, the web application could evolve into a massive monolith with hundreds of files and just too many lines of code to count. And since the entire codebase is coupled and many processes depend on each other, if something goes wrong in one place, the entire application could be affected. This makes debugging, testing, and updating existing code extremely difficult. Moreover, if a new developer joins the project, they will spend considerable time understanding the existing codebase rather than implementing new features.
To address all these issues, software engineers had to come up with a solution that allows developers to deploy applications fast, but also scale quickly. So they came up with a different approach called microservice architecture.
Microservices Architecture
The microservices architecture has its roots in two Computer Science principles:
- Separation of Concerns: “a design principle for separating a computer program into distinct sections such that each section addresses a separate concern” (Wikipedia). In the context of web architectures, this principle says that all of the code for a particular feature of the application should be separated into a dedicated microservice.
- Single Responsibility Principle: introduced by Robert C. Martin, this says that “every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class, module or function” (Wikipedia). Simply put, each class or method in a microservice should have just one responsibility at a time.
Hence, in a microservice architecture, that monolith codebase is broken down into multiple smaller pieces that function entirely independently from each other. These pieces are called microservices, and they have their own logic and codebase. In other words, instead of having a huge codebase organised into a single project, in a microservice application, the logic is divided into multiple projects, each having a clear purpose and function. Figure 3 illustrates a microservice application structure.
Based on this structure, we can assume that the application architecture looks as in Figure 4:
To better understand this model, think of microservice architecture as a hospital. Hospitals have a reception, but the reception won’t help you with your health problem. Instead, it will forward you to the right department. A microservices application works just like that, too. In this approach, the role of the main application is to glue and combine everything together, rather than to implement all of the logic within itself.
Advantages of microservices architecture
In the last few years, this architecture model gained popularity, and key players such as Netflix, Amazon, or Airbnb switched from an entire monolith codebase to microservices. And there are several good reasons for that.
For large applications that need to scale, a microservice architecture facilitates scaling with lower cost, compared to a monolithic architecture. Why? Because you don’t have to update an entire codebase to add a new feature. Instead, you can easily scale just an individual component.
Also, since each microservice exists in a separate container or server and is treated independently, this approach makes it easier to modify and test existing features, as well as implement new ones. And because microservices are decoupled, a faulty microservice is less likely to affect the entire application.
Disadvantages of microservices architecture
Microservices architecture trades code complexity for system complexity. So instead of having a massive codebase, you will end up with a massive infrastructure because each microservice uses a separate server/container. Hence, managing a microservice application may require enormous efforts, skills, and resources. After all, software engineering and security are all about smart tradeoffs.
Conclusion
Keep in mind that monolithic and microservices architectures are not a replacement for the multi-page, SPA, or widget architectures we discussed in the previous post. They are an additional layer that sits on top of an application’s existing architecture. In the next post in this series, we look at one of the core components of the Web: the URL.