Hoang Thu
Hoang Thu
Restructuring an Enterprise
Monolith into a Microservices
Architecture
As a result, the thesis aims to assist the transition from a monolith to the
microservices architecture. It offers valuable insights into the practical implications of
implementing microservices within enterprise project architectures.
In conclusion, the thesis reflects on the attainment of the project's goal to transition
from a monolith to the microservices architecture. It underscores the significance of
this architectural transformation in enhancing system scalability, flexibility, and
maintainability. Furthermore, it emphasizes the relevance of the methodology
employed in guiding this transition and the tangible outcomes achieved therein.
List of Abbreviations
1 Introduction 1
2 Monolith architecture 2
3 Microservices architecture 6
4 Designing microservices 11
5.1 Planning 19
5.1.1 Current monolith architecture challenges 19
5.1.2 Needs of microservices 20
5.2 Designing microservices architecture 22
5.2.1 Evaluating system operations 22
5.2.2 Dividing monolith service to microservices 23
5.3 Implementing restructuring from monolith to microservices 27
5.3.1 Frontend 27
5.3.2 Backend 28
5.4 Infrastructure and cloud 29
5.5 Evaluation 30
6 Conclusion 31
References 33
List of Abbreviations
XML: Extensible Markup Language. A language that lets the user define
and store data in a sharable manner.
1 Introduction
2 Monolith architecture
typically involve interactions with databases for tasks like reading or storing data
(see Figure 1). [3.]
Figure 1. A single process monolith packages all the code into one place. Copied
from Newman (2019) [3].
debugging process is easier since the codebase is located in one package. This
supports following a request and tracking an issue. Testing is simplified with a
centralized code base for either unit or end-to-end. Performance is optimized
because a centralized repository can enable one API to handle tasks that might
necessitate multiple APIs in a microservices setup. With these advantages, the
monolithic architecture provides simplicity in development, deployment, and
management, requiring reduced infrastructure and operational overhead. [4.]
2.4 Summary
3 Microservices architecture
The next stage in the history of microservices was 1999 when Microsoft
introduced Simple Object Access Protocol (SOAP). SOAP was described as an
approach to simplified object method usage via HTTP. SOAP was utilized until
roughly 2005 to 2007 when the technology community started to reject it. In
2008, developers started to shift toward REST, introduced by Roy Fielding. It
gained popularity in 2010 because of its scalability, portability, and ease of use.
Roy Fielding's work on REST highlighted flexibility, and it is commonly used in
conjunction with microservices for its adaptability and scalability. [7.]
With microservices, reducing the risk while adopting new technology is a major
advantage. In a monolithic architecture, applying a new framework or database
will influence most of the system. However, in microservices, selecting a low-
risk service when exploring a new framework minimizes the negative impact.
Establishing multiple technologies does not come with overload. [8.]
Furthermore, testing becomes a difficult task since the scope of the system is
large. Running tests across multiple services is time-consuming. False
negatives occur such as breakdown services or network timeout causing a test
to fail. As a result, as the scale of the system grows, and the investment for
testing end-to-end increases as well. Additionally, testing these service
dependencies can pose challenges, especially in scenarios where the
application is undergoing frequent changes. Latency is another drawback of
microservices. Processing in microservices may be divided across services
which can cause latency. [8.]
Data consistency can be challenging when each microservice manages its own
data. Skill set evaluations are important, as microservices are highly distributed
systems. The team's expertise plays a crucial role in the successful
implementation of this architecture. [8.]
4 Designing microservices
not to be suitable for brand-new products or start-ups, since the domains will be
drastically modified in the future. Furthermore, shifting the domain model results
in adjusting the service boundaries, which leads to changes required to be
coordinated across service boundaries. The human resources maintaining the
microservices are another factor to consider. Limited resources in developing
microservices cause overload work since deployment and management
services themselves require a developer to handle the work. This is usually
described as “microservice tax”. When software is deployed and managed by a
customer, microservices is not a suitable selection. As mentioned, the
deployment and operational domains are complex parts of microservices and
managing them requires knowledge and expertise. Expecting customers to
accomplish the tasks is not appropriate. [8.]
related elements. This concept is crucial for incrementally designing the service
architecture, focusing on one operation realization at a time. [11.]
The next stage is evaluating the architecture to pinpoint architectural flaws that
potentially become issues. Assessing the architecture requires a deep
understanding of business priorities. These priorities provide the guiding
principles for assessing whether the architecture meets the needs and goals of
the organization. Business priorities evolve; therefore, reassessment is
essential. Effective team structure is crucial to minimize unnecessary
communication across teams. Adopting a microservices architecture promotes
the establishment of small, specialized, cross-functional teams. Microservices
are separate services that communicate with each other to handle tasks.
Establishing the right communication method ensures they talk reliably. In a
microservices setup, an API gateway is a crucial element. Directly exposing
services to clients can lead to issues in terms of control, manageability, and
reliable communication. Accessing the API Gateway thoroughly minimizes
issues that appear in the future. [12, 13.]
Lastly, after identifying issues from the evaluating process, refactoring the
architecture is done the next step to eliminate those. Refactoring in a
microservices architecture occurs at four levels:
Overall, the CPQ process initiates by creating an offer, which involves fetching
information from another program called M-files. Each offer comprises one or
multiple positions, each of which includes various calculations. Each calculation
is a heat exchanger configurator, which comes in six different types. That is the
configuration part. Following the configuration of a heat exchanger in the pricing
phase, sales personnel begin adjusting the pricing and supplementing
additional documents and information, such as terms of delivery, payment
methods, warranty policies, and customer notes. Finally, the quoting phase
entails exporting documents containing heat exchanger details, pricing, and
offer specifics to be sent to the customer. Additionally, the CPQ project includes
integration of an API service for customers.
5.1 Planning
Secondly, developing the monolithic CPQ starts becoming a difficult task since
the project becomes larger every day with new features added. Functionalities
overlapping each other create complexities during development because
developers cannot easily identify the relationships between different functions.
The uncertainty regarding whether changing one function will affect others
20
Moreover, the CPQ application uses one backend service which leads to
difficulties and delays in deployment. Updating only the offer database schema
does not interfere with position, calculation, and heat exchanger schema.
However, since they are all part of one database, any changes to the offer
database require migration, causing delays for all other features and backend
functionalities. This affects the business logics which are not related to offer
lead to delay in performance of the application. Reliability is another factor that
is disturbed. An issue appears in a heat exchanger configurator functionality
causing a breakdown resulting in an incident of the entire backend service
including offer, position, and API service. This situation could be mitigated if
each business logic had its own dedicated backend service. In such a setup,
outages in one independent service would not impact the others.
Lastly, the monolithic architecture has limitations in flexibility scaling. The heat
exchanger used an old calculating thermophysical properties database called
REFPROP which operates on a single thread. Since the backend contains the
entire business logic, it needs a powerful virtual machine to host it. Combining
with REFPROP which only operates in a single thread result in scaling ten
powerful machines for one small business logic. Consequently, scaling
becomes financially burdensome.
Moreover, updating the database schema in a service does not evolve since
each service has a distinct database. As a result, running migration after each
update does not affect other services. Developing new functionalities for a
certain service does not impact other services. Deployment becomes less
complex since each service is independently deployable as developing or
updating only requires deployment services that have been changed. Reliability
of the code is another factor is improved. Each business domain is a distinct
service; therefore, an outage in a service backend or database does not lead to
a breakdown in other services.
virtual machines is more financially beneficial than ten powerful virtual machines
served for a small business purpose.
The next phase of the journey is configuring pricing. Users have the ability to
adjust the price for each part of the heat exchanger unit, add discounts, and
update the final price. Configuring the amount of each part of the machine, add
specification comments for each part of the unit are necessary functionalities.
Adding additional information such as terms of delivery, payment methods,
warranty policies, and customer notes is a part of the adjusting pricing process.
23
Lastly, the quoting process is the stage to export necessary documents to send
them to the customer. The quoting phase includes exporting heat exchanger
data into PDF format from the configuration form. Additionally, quoting allows
users to order and receive technical drawings in their mail from another service.
Moreover, exporting the offer and the pricing for the customer is the most
important requirement for this stage.
The system operations discovery is documented into a diagram (see Figure 6).
Heat exchangers contain of six different types of units. However, not every
calculation and position require fetching six different types of heat exchangers.
Each type of heat exchanger contains multiple different entities as well as
distinct logic to calculate the thermomechanical design. As a result, it is suitable
for separating each type of machine into an independent service leading to six
25
additional microservices with distinct databases for each of the services (see
Figure 8).
At the moment, the pricing logic is inside the heat exchanger services since
each heat exchanger type has a different calculating price logic. The way to
calculate the price is determined between the R&D and sales departments;
therefore, the logic is updated frequently. As a result, the pricing logic affects
the heat exchanger services. Consequently, there is a need to separate pricing
into an independent service. Given that CPQ is an ongoing project, the decision
to separate pricing logic into an independent service will be carefully evaluated
and determined.
27
5.3.1 Frontend
Handling the fetching, caching, and synchronizing data with the server, the
library called TanStack Router is utilized. The TanStack router is described as a
React router that is completely type-safe, featuring integrated data fetching,
caching with stale-while-revalidate and first-rate search-param APIs [16]. Each
team is responsible for managing the API client specific to their service. Within
a team, every frontend member possesses knowledge of handling validation,
required parameters, return types for each call, and error handling. Utilizing the
TanStack router not only enhances the development experience but also
ensures that data remains up to date. TanStack usage also limited the delays in
fetching and displaying the data by initially delivering the data from the cache.
Subsequently, it synchronized with the server to verify if any updates have
occurred. If there are discrepancies between the server data and the cache, the
TanStack router updates the cache accordingly and triggers a component re-
render.
28
5.3.2 Backend
Since the team has multiple JavaScript developers who can work with the
backend and frontend, the team has made a decision to write the backend
using the Nest framework.
app.connectMicroservice({
transport: Transport.TCP,
options: {
host: env.APP.TCP_HOST,
port: env.APP.TCP_PORT,
},
})
app.enableCors({
origin: [
'http://localhost:3002',
],
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
allowedHeaders: [
'baggage',
'authorization',
'content-type',
],
})
app.setGlobalPrefix('orp-api')
app.use(json({limit: '10mb'}))
await app.startAllMicroservices()
await app.listen(env.APP.PORT)
}
bootstrap()
@Controller('internal')
@UseFilters(RpcHttpExceptionFilter)
export default class InternalServiceController {
private _entityKeys: string[]
constructor(private readonly orpService: OrpService) {
this._entityKeys = listEntitykeys(OrpEntity)
}
@MessagePattern(TCP_MESSAGES.ORP.OFFER.GET_BY_ID)
async getOfferById(offerId: string): Promise<OfferDto> {
return this.orpService.getOfferById(offerId)
}
}
from hardware and software objects. As a result, containers are versatile tools
for building applications. [18.]
5.5 Evaluation
After deploying and testing with the users along with the developing process,
conclusions have been made about the restructuring process from monolith to
microservices project. Firstly, the developing process is pleasant for the
developers. Dividing the monolith into microservices and each team being
responsible for one service keeps the business domains and functionalities
clear. Feedback from developers is positive since services are isolated,
resulting in implementing new features and in the functionalities being less
complex. There is no need for them to verify whether altering this functionality
impacts any other functionalities. This reduces the time for developing new
features since developers do not have to wait for each other to ask and test if
any errors happen in the existing functionalities when the new features are
added. Onboarding new developers into a team is easier since the scope of the
service is limited, and they are only required to understand the microservice
they develop. With the remaining services, they can take time to investigate
later on. This creates an improvement in the financial situation for the
31
Secondly, heat exchangers are the only services that require REFPROP. The
monolith is a single package that leads to deploying ten powerful virtual
machines to support concurrent users creating financial problems for the
company. With microservices, heat exchangers are separated into
independently deployable services resulting in scaling ten normal virtual
machines to support concurrent for REFPROP. As a result, the cost of hosting
virtual machines was reduced drastically. This means that the major purpose of
the implementing microservices project achieved.
Moreover, the customers utilizing the API integration service are highly
satisfied. The service has its own dedicated team to support the client.
Moreover, the server is not affected by the internal process. The service is
isolated, which means that the incidents of the internal services do not outage
the API integration server. The stabilization of the API integration service is
ensured. Another purpose is resolved by adopting microservices.
6 Conclusion
The main purpose of this project was to provide key elements and information
for restructuring a monolithic architecture to a microservices architecture. In the
first section, the main concept of the monolith architecture was introduced as
32
well as its benefits and challenges. It was important to understand the monolith
concept thoroughly before a decision to shift to another architecture was made.
References
https://microservices.io/post/architecture/2023/02/09/assemblage-
architecture-definition-process.html>. Accessed 4 April 2024.