Dawid Wieczorek | Software Development | 10.11.2021
Today’s applications are developed in a continuous delivery model and new features need to be implemented by development teams without affecting the availability of the system. Microservices are the answer to problems related to the creation and maintenance of monolithic applications, and microservices architecture is becoming state-of-the-art in software development. Which projects will this architectural style work in, and when is it better to stick to monolith application architecture?
The concept of microservices architecture first appeared in IT around 2013. Since then, its popularity seems to have been moving in one direction – up! We can find confirmation of this in the 2020 O’Reilly report “Microservices adoption”, which shows that 77% of respondents use microservices architecture. At the same time, as many as 92% of respondents described the use of microservices as a success from the perspective of the expected payoffs that this approach brings.
In another survey by IBM Market Development & Insights, over 1,200 people from the IT industry were asked to share their opinions, including technical directors, managers and programmers working in companies that use or plan to use microservices.
The results are clear:
Although this is obviously a very uncertain measure, from the developers’ own perspective – judging by the project descriptions in job postings – I could say that in practice most projects are currently created using microservices architecture. Despite the fact that we have to look at such descriptions with an element of uncertainty, we can see that microservices are quickly becoming standard in the IT world.
One of the biggest challenges of microservices architecture is a strong dependence on infrastructure (server side, network, etc.), and thus an increased need to invest in development. A few years ago, however, it was a much greater challenge than today. In response to the needs of the new model, a wide range of tools have been developed to improve work in a distributed environment.
Another significant change that occurs with the development of microservices is the presence of the network as an unstable element that cannot be avoided. Every developer eventually has to deal with networking problems, both in terms of transport and the much more complex tools required for debugging.
There is also a boom in demand for the above-mentioned tools supporting work and for debugging of the container application, and today we can take advantage of many monitoring, logging and tracing solutions.
Solutions such as Prometheus, ELK or AWS CloudWatch address the challenges related to maintaining or debugging applications in a distributed environment.
The emergence and ultimate success of microservices, of course, did not come out of nowhere. It is rather a response to the difficulties associated with the classical approach, which in many cases outweigh the advantages of the monolithic approach.
From a business perspective, we can list many issues that may affect the user experience, and thus – the final success of the application:
The possibility of using new technologies, the introduction of which would be too costly and require more time for developers (or even the necessity of hiring new ones), is significantly reduced.
Looking at this from the perspective of the developer working on the monolith, we can additionally mention a few more disadvantages:
Now let’s move on to the capabilities made available through the use of microservices.
Most of the benefits of building distributed systems are the result of creating a proper division of responsibilities for given microservices and determining the ways of communicating between them. The goal is to create a strong consistency amongst websites and at the same time a loose connection between them. In other words, things that usually need to be changed together should belong to one site.
Without adequate division, instead of benefiting from microservices (services can be deployed independently and are scalable) we can end up with a project which is inefficient or difficult to maintain. In practice, it is obviously easier said than done – initial assumptions or requirements may change later. For this reason, being able to easily make changes is another crucial aspect in the design of any application.
Domain-driven design (DDD) is a key approach when designing microservice architecture, both while carrying out monolithic service decomposition and creating a system from scratch.
DDD, introduced in Eric Evans’ book, is a set of principles and patterns aimed at supporting the development of distributed systems based on the business domain model as the subject of the developed software. A team of developers, together with business domain experts, create a business model in a common language (so-called ubiquitous language). Then the created model is translated into particular services, communication protocols between them are established and teams responsible for given services are formed. Using event storming can also be helpful throughout the process. DDD patterns are designed to help you to comprehend the domain and its dependencies. From here it is not far to delineate the boundaries in the domain, and split it into services.
In an e-commerce platform which has been available for many years now, a new business requirement has emerged for the mass creation of new file-based offerings. The tool was to be mainly used by sellers offering a wide range of products, who could use the tool to improve and automate the interaction with the platform in terms of creating and editing their offers.
This platform, although created as a monolithic one, has been divided and developed using microservice architecture. The duty entrusted to one of the JCommerce development teams was therefore to create a new microservice (several of them were eventually created) responsible for this functionality. Work on the solution was carried out without interfering with the rest of the application’s multiple services, the development of which could proceed independently. The only point of contact with the rest of the platform was another microservice, and communication and implementation details were agreed between the teams responsible for both services.
Also, the majority of decisions about the technology stack (such as a database or even using different programming languages) were left to the team. After production deployment, the JCommerce team is able to dynamically scale the number of service instances according to the number of inquiries from users. Such autonomy is crucial to the development of applications that even hundreds of teams are working on collectively. It is hard to imagine the effective implementation of such functionalities in the case of monolithic applications.
Unfortunately, the answer to this question must be evasive – it depends. When deciding on a given model, we have to compromise, i.e. we agree to take it together with its strengths and weaknesses.
If we are considering dividing an existing monolithic application, the decision may be simpler, motivated by all the issues that the monolith can cause. In this case, one of the proven approaches is cutting off smaller components from the main block, until finally new functionalities can be created in complete isolation and the smaller central monolithic application is gradually extended.
However, if we start building an application from scratch, one of the key factors is the size of the target application. When creating an MVP of an application, the most important thing is the speed of functionality delivery, at the expense of other priorities. According to the YAGNI rule (You Ain’t Gonna Need It) it makes no sense to invest in using excessively sophisticated tools, if we are not sure that the application will attract the required level of interest.
Such a situation speaks in favor of using a monolith, which will be divided at a later stage – an interesting solution may be the use of the architecture of the so-called modular monolith, in which the functionalities are divided into individual modules created within one application.
However, if we know that the size of the target application justifies the initial investment, microservices architecture is the most suitable choice.