0% found this document useful (0 votes)
14 views

Hoang Thu

This document discusses restructuring an enterprise monolith architecture into a microservices architecture. It defines monolith and microservices architectures, explaining their concepts, benefits, challenges, and history. It then covers designing microservices by evaluating needs, discovering operations, defining subdomains, and designing the architecture. The document presents implementing the transition from monolith to microservices, including planning, designing the new architecture, and executing the restructuring process.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

Hoang Thu

This document discusses restructuring an enterprise monolith architecture into a microservices architecture. It defines monolith and microservices architectures, explaining their concepts, benefits, challenges, and history. It then covers designing microservices by evaluating needs, discovering operations, defining subdomains, and designing the architecture. The document presents implementing the transition from monolith to microservices, including planning, designing the new architecture, and executing the restructuring process.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Thu Hoang

Restructuring an Enterprise
Monolith into a Microservices
Architecture

Metropolia University of Applied Sciences


Bachelor of Engineering
Information Technology
Bachelor’s Thesis
9 April 2024
Abstract

Author: Thu Hoang


Title: Restructuring an enterprise monolith into a microservices
architecture
Number of Pages: 41 pages
Date: 9 April 2024

Degree: Bachelor of Engineering


Degree Programme: Information Technology
Professional Major: Mobile Solutions
Supervisors: Ilkka Kylmäniemi, Senior Lecturer

This thesis explores the process of restructuring a complicated enterprise monolith


structure to a microservices architecture. The microservices architecture is rising as a
solution for complexity in managing and constructing software systems. The aim of
this process is to enhance the flexibility and scalability of enterprise systems.

The methodology section examines a comparative analysis of monolith and


microservices architectures. It delineates the steps involved in designing
microservices, evaluating the need for their adoption, discovering system operations,
defining subdomains, and designing the services architecture. Furthermore, it
elaborates on the implementation process, including planning and designing a
microservices architecture, and executing the restructuring process. The process of
designing microservices and transition from a monolithic to a microservices
architecture for enterprise projects is presented. The results of the restructuring
process are positive.

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.

Keywords: microservices, monolith, restructuring monolith into microservices


___________________________________________________________
Contents

List of Abbreviations

1 Introduction 1

2 Monolith architecture 2

2.1 Main concept 2


2.2 Benefits of monolith architecture 3
2.3 Challenges of monolith architecture 4
2.4 Summary 5

3 Microservices architecture 6

3.1 Main concept 6


3.2 History of microservices architecture 8
3.3 Benefits of microservices architecture 9
3.4 Challenges of microservices architecture 10

4 Designing microservices 11

4.1 Evaluating the need for microservices 11


4.2 Discovering system operations 13
4.3 Defining subdomains 14
4.4 Designing services architecture 15
4.5 Evaluating and refactoring the microservices architecture 17

5 Implementing restructuring from monolith to microservices 18

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

SOA: Service-oriented architecture. A software development method that


uses modular components called services to create business
applications.

API: Application programming interface. Rules or protocols that facilitate


software communication for exchanging data, features, and
functionality.

IDE: Integrated development environment. A software tool that helps


programmers code efficiently.

XML: Extensible Markup Language. A language that lets the user define
and store data in a sharable manner.

URI: Uniform Resource Identifier. A distinctive character sequence used


to designate a logical or physical resource employed in web
technologies.

HTTP: Hypertext Transfer Protocol. An application-layer protocol primarily


used for transmitting hypermedia documents.

URL: Uniform Resource Locator. The web-based address of a particular,


unique resource.

REST: Representational State Transfer. An architectural style for providing


standards between computer systems on the web.

SOAP: Simple Object Access Protocol. A messaging protocol exchanging


structured information in computer networks.
SaaS: Software as a service. A software licensing and delivery model in
which software is centrally hosted and licensed on a subscription
basis.

gRPC: Remote Procedure Call. A cross-platform open-source high


performance remote procedure call framework.

PDF: Portable Document Format. A file format developed by Adobe in


1992 to present documents.

CI/CD: Continuous integration and continuous delivery. Combined practices


of continuous integration and continuous delivery.
1

1 Introduction

In recent years, the microservices architecture has gained significant attention


because of its potential to address the challenges of scalability, flexibility, and
maintainability in large-scale applications. The microservices architecture
decomposes a monolith architecture into independently deployable, loosely
coupled services. Each service is responsible for a specific business function.
This shift in approach offers numerous advantages. It enhances flexibility, aids
in isolating faults, and enables the independent scaling of components.

Firstly, the thesis defines the fundamentals of monolithic and microservices


architectures, structured into three primary segments: explaining the main
concepts of each approach, outlining the advantages, and addressing the
disadvantages. Furthermore, the thesis delves into the evolution history of
microservices.

Next, the thesis presents the principle of designing a microservices software


system. The planning phase to evaluate the need for microservices and
discovering system operations are addressed. After that, defining subdomains
and designing services are explained. In addition, the process of re-evaluating
the architecture and refactoring it is discussed.

Finally, a practical case of developing an enterprise microservices architecture


based on an original monolithic is presented. The process started with a
planning phase, addressing the challenges of the formal monolith architecture,
and highlighting the need for the transition. The next phase of designing the
microservices architect is explained. It consisted of evaluating the system
operations and separating the monolith into services for the new architecture.
Implementing the microservices architecture, the most important phase, is
explained thoroughly. The process of testing and deploying microservices is
addressed as well. Lastly, the effectiveness of the microservices architecture
compared to the previous monolithic setup is evaluated.
2

In conclusion, the thesis outlines the benefits and challenges experienced


during the transition process. Additionally, it evaluates the efficiency
improvements achieved by transitioning to the new microservices architecture.

2 Monolith architecture

2.1 Main concept

The monolithic architecture is a traditional approach to developing a software


system. A monolithic architecture consists of a single, expansive computing
network with a unified code base that handles all business logic. The monolith
architecture is a single deployable unit, incorporating all subdomains and
utilizing a singular database. Any changes to such an application require
modifying the entire stack, accessing the code base, and deploying an updated
version of the server-side interface. A monolith provides a convenience in code
management, reducing the cognitive load, and facilitating the deployment
process since all components can be released simultaneously. [1.]

A monolithic application integrates all its components, including the user


interface, business rules, and data manipulation, into a single application layer.
While the data might physically reside in a remote location, the logic for
accessing it is embedded within the application itself. An example of a
monolithic application is Microsoft Word, where the user interface, business
rules, and file access routines for manipulating document data are all tightly
integrated as part of the application. [2.]

When discussing monolithic systems, the most common type of monolithic


architecture is the Single Process Monolith, where all the code is deployed
within a single process. While there might be multiple instances of this process
for reasons such as ensuring robustness or facilitating scalability,
fundamentally, all the code is contained within a single entity. In practice, these
single-process systems often resemble simple distributed systems, as they
3

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].

Another form of the monolithic architecture is the distributed monolith. This


configuration involves a system comprising multiple services that must be
deployed together for various reasons. Although the distributed monoliths might
fit of the definition of a SOA, they often fail to fulfill the expectation of a SOA. A
distributed monolith experiences disadvantages of both distributed and monolith
systems without inheriting the advantages of both. These distributed monoliths
typically appear because of a lack of emphasis on crucial concepts like
information hiding and cohesive business functionality. Minor adjustments can
unexpectedly break the system due to the highly coupled services. [3.]

2.2 Benefits of monolith architecture

A monolith architecture, especially a single-process monolith, presents


numerous of advantages. Firstly, all source code is in one package leads to a
simplified development process. It reduces the need for specialized knowledge;
therefore, the developing process for developers is simpler. Secondly, the
4

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.]

Furthermore, the monolithic architecture can scale up to a certain point,


managing moderate traffic and workload effectively. Simple deployment
topology is the key aspect of the benefits of a monolith. Compared with
microservices or distributed services, where multiple deployments need
handling, a monolith only requires one deployment. As a result, many pitfalls
can be avoided [4]. As a code base is in a unified repository, reusing code
across the package is straightforward. With a distributed system, reusing code
from other services can be difficult since several factors need to be considered
such as breaking out into libraries, duplicating the code, or dividing the shared
functionalities into a new independent service. [4.]

2.3 Challenges of monolith architecture

The monolithic architecture, single-process and distributed one, presents


several drawbacks. As the monolithic repository grows, the size of the code
base becomes larger, the development process turns into a complex journey.
The size and intricacy of the code base become an obstacle and surpass the
understanding of developers. Different developers need to change the identical
piece of code or delay deployment by different teams due to delays in
developing functionalities. Confusion is created between management and
different developer teams in ownership and decision-making in the repository.
This can cause delivery contention. Future feature implementation turns out to
be a time-consuming task since each contribution to the repository increases
the complexity. [4.]
5

Furthermore, the scalability of the monolith architecture is limited. Each


component in the structure cannot be scaled individually since scaling means
scaling the entire application. Daily tasks suffer from delay due to the
overloaded IDEs, resulting in slow application start-up. These factors
collectively affect productivity and hinder the agility of the development team.
[4.]

Moreover, deploying changes in a monolithic environment proves to be a


difficult task as the size of the monolith grows. Frequently deploying new
features and components coupled with others creates a vulnerability for the
project since components rely on each other. Specific testing is created for new
features or components to ensure they do not affect the remaining components
and the entire application. This creates a lengthy deployment process, which
results in slowing down the pace of development and introducing complexities
and risks in managing and coordinating large-scale updates. [4.]

Lastly, the monolithic presents challenges in technological evolution. Monoliths


is a traditional way of developing applications. As a result, it limits the adoption
of newer frameworks and languages since it may require rewriting most part of
the application. Consequently, the application is restricted to the ability to evolve
and adapt to market trends and support customer needs.

2.4 Summary

In conclusion, while monolithic architecture presents several advantages, its


challenges need to be recognized as well. The monolithic architecture is
suitable for small-scale applications. The simple setup, development, and
deployment process are the main keys to consider when selecting an
architecture. The monolith architecture is suitable when the developer team is
lean and the application is not complicated. Despite that, software systems are
evolving simultaneously and the disadvantages of monolith need to be taken in
consideration. The limitation to adopting new technology and language
combined with the complexity in scaling leads to difficulty in application growth.
6

Moreover, transitioning away from a monolithic architectures requires thoughtful


planning and investment in tooling, processes, and skill development. The
journey of refactoring from monolith to microservices experiences difficulties
such as decomposing codebase, managing the increasing complexity as well as
evaluating the scalability and maintainability. Ultimately, the choice of
architectural pattern should align with the specific needs and goals of the
organization. Focusing on continuous innovation and delivering value to end-
users are important factors to consider. Monoliths is not a traditional, outdated
architecture. If the purposes of the project are achieved by using monoliths and
the benefits outweigh the challenges, the monolithic architecture is a choice.

3 Microservices architecture

3.1 Main concept

The microservice architecture, also referred to as microservices, is an


architectural approach that organizes an application into a set of services with
specific characteristics. These services are designed to be independent in
deploying and developing. They are loosely coupled to ensure changes in one
service do not disrupt the others. Each service contains one specific business
logic and is owned by a small developer team. Microservices are organized
around distinct business capabilities, making it easier to manage and scale
individual components. [5, 6.]

One of the most important concepts of microservices is independently


releasable. Changes created in one microservice can be deployed
independently to the user without impacting the other remaining services. This
is the method to build a deploying pipeline for the software system. To ensure
independent deployment, the services require to be loosely coupled. The ability
to develop one service without interfering with the others is important. To create
loosely coupled services, clear, well-defined, and stable contracts between
7

services have to be developed. Domain-driven design is utilized to design the


microservice boundaries. Organizing services relying on business domains
simplifies the release of new functionalities and facilitates the recombination of
microservices to deliver new features to users. A frequently used microservices
pattern is the three-tiered architecture. Each layer represents a distinct
boundary, with each boundary establishing a technical functionality (see Figure
2). [6.]

Figure 2. A simple three-tiered architecture. Copied from Newman (2019) [6].

Automation such as continuous integration, deployment, and automated testing


is essential for reducing manual steps and workload. Microservices need to be
designed for failures and have quick recovery. These principles contribute to the
creation of autonomous teams to develop and maintain a microservices
architecture. [6.]
8

3.2 History of microservices architecture

In 2005, the term "Micro-Web-Services" appeared in Dr Peter Rodgers's


presentation on cloud computing. During the presentation, he challenged
established notions by promoting the adoption of software components that
facilitate micro-web-services. Within his presentation, the groundwork for the
functional framework for microservices was introduced. Furthermore, he
explained the well-structured micro-web-services platform where the principles
of REST and the World Wide Web are integrated, cooperating with Unix-like
scheduling and pipelines. This approach aims to create flexibility and simplicity
in SOA. [7.]

The journey to microservices architecture can be traced back to IBM's release


of Enterprise Java Beans in 1997. It was an early attempt to introduce smaller
services in web-related software components. However, it had limitations such
as complexity, complicated debugging, and not being user-friendly. This led to
the emergence of SOA, emphasizing self-contained services that communicate
across different platforms with loose coupling. [7.]

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.]

In May of 2011, during a workshop near Venice, Italy, a group of software


architects introduced the term "microservice" to describe a new architectural
style they had been exploring. A year later, in May of 2012, the name
“microservices” was adopted for their work. Their experimentation primarily
revolved around the development of continuously deployed systems and the
9

integration of the DevOps philosophy. This architectural approach gained


popularity rapidly. [7.]

3.3 Benefits of microservices architecture

The adoption of microservices offers numerous advantages in the modern


software development field. Firstly, since microservices consist of multiple
independent, collaborative services, different technologies and languages for
each service can be established (see Figure 3). This allows flexibility in
selecting the most suitable tool for each functionality. If one functionality
requires switching to a different technology, it will not disrupt the other services.

Figure 3. Different technologies and languages are used in different services in


a social network microservices architecture. Copied from Newman (2019) [8].

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.]

A key advantage of microservices is robustness. If a service fails, the failure


does not cascade. The non-failing services continue to proceed since the failing
service is isolated from the remaining ones. However, in a monolithic
10

architecture, one failure service results in the breakdown of the system.


Handling failure in microservices is a major aspect that needs considered
thoroughly. [8.]

One small change to a component in a monolith architecture requires the


deployment of the entire system in order to release the feature to the user. This
leads to one of the major advantages of microservices being ease of
deployment. Since every service is independently deployable, modification in
one service does not affect the system. Independently deploying the changed
service reduces the probability of encountering failure in other components or
data. [8.]

Lastly, microservices have established the opportunities for the reuse of


functionality. Functionality is allowed to be consumed by various methods and
purposes. Functionality is exposed across the system resulting in the open
capability to reuse it for the web, native mobile applications, the mobile web, or
wearable devices. Microservices are shown to have advantages in complex and
scalable software systems. [8.]

3.4 Challenges of microservices architecture

Transitioning to a microservices architecture offers various benefits, but it is not


without its challenges. One of the primary challenges is the increased
complexity. While each microservice is simpler, the overall system becomes
more intricate due to the numerous moving parts involved. This complexity can
create difficulties in system management and coordination. [8.]

Monitoring and troubleshooting are the next difficulty in developing a


microservices architecture. In a traditional monolithic architecture, monitoring is
fairly simple. The monolithic architecture has a small number of machines, and
they are often all well-performed, or all failed. However, the microservice
architecture contains numerous machines which require monitoring. This results
in difficulty in monitoring and demands resources to follow the status of the
11

machines. Security is another point to consider when establishing


microservices. Since a considerable amount of information passes through the
network between the services, data becomes more vulnerable. Protecting the
data and ensuring the endpoints are secure is important. [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

4.1 Evaluating the need for microservices

Despite the benefits the microservices architecture brings, it has disadvantages


as well; therefore, adopting microservices requires careful consideration. It is
important to understand the demands of the project, the expertise needed, and
the technology landscape in order to decide the architecture approach that is
used. [8.] Understanding the concept of microservices is important to determine
to implement it.

The criticality of establishing clear and consistent service boundaries is


important for defining a microservices architecture. Therefore, it often appears
12

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.]

Microservices is a suitable choice for a project on which organizational


boundaries are declared clearly. Adopting microservices allows developers and
teams to work in the same system without interfering with each other. As a
scaling team experiences rapid growth, adopting a microservices architecture
accommodates the expanding needs of the product. Software as a Service
(SaaS) applications are expected to operate continuously without downtime;
therefore, microservices are a suited selection. The independent releasability is
a major factor for SaaS applications since these applications can deploy new
features without experiencing downtime. Cloud platforms are utilized the most
with this architecture. A wide selection of services and deploying mechanisms is
provided by the public cloud vendors. Specific service requirements are
complemented more easily by the cloud service that is the most suitable to
implement. Microservices present benefits for organizations providing services
to customers through various channels. Above everything, a microservices
architecture provides flexibility as the system grows. [8.]

In summary, while microservices offer scalability and flexibility, their adoption


requires careful consideration. Assessing project demands, expertise, and
technology landscape is crucial. Clear service boundaries are essential.
However, they excel in accommodating rapid growth and continuous operation,
13

particularly in SaaS applications. Cloud platforms enhance their benefits.


Ultimately, microservices provide flexibility and scalability as systems evolve.

4.2 Discovering system operations

The next phase after selecting microservices as the architecture is defining


system operations. A system operation refers to an externally callable function
or behavior that is implemented within an application. Parameters and an
operation return value belong to a system operation; therefore, it is a method
that the application implements. Users or other applications are usually the
external factors invoking an operation system. For instance, in an e-commerce
platform, common user-triggered system operations may include actions like
registering a customer (createCustomer()), placing an order
(createOrder()), and canceling an order (cancelOrder()). [9.]

Moreover, system operations are independent of technology. A combination of


technologies is established during the implementation of the operation such as
an HTTP or gRPC request synchronously or a message asynchronously. It is
important to document the system operations. For each system operation,
describing the operation consists of signature (parameters and return value
types), behavior (the aggregates that are written and read), and non-functional
requirements. Defining system operations returns one or many sequence
diagrams to illustrate the complexity of the operations. The interactions between
users and the internal and external applications are described in Figure 4.
Lastly, the domain model explains the data sets that the operations read and
write preparing for the next process which refines it into subdomains. The result
of a defining operation systems process is presented in Figure 4. [9.]
14

Figure 4. The process of defining system operation. Copied from Richardson


(2023) [9].

4.3 Defining subdomains

In the previous phase, system operations are discovered containing business


entities. In this phase, defining the subdomains containing the business entities
is done. The result of this process is gathering information for each subdomain
in order to group the subdomains into services in the next phase. A subdomain
represents a team-sized portion of business functionality, also known as a
business capability. It includes the entities or aggregates that are manipulated
by system operations. A collective of subdomains creates a service. [10.]

To create a subdomain, firstly, it is necessary to define each subdomain


modeling based on business entities. Secondly, it is important to consider the
complexity, ownership, testability, technology stack, resource requirements,
15

domain-specific software development regulations, and business criticality when


creating a subdomain. One key factor when creating a subdomain is design-
time coupling. Avoiding narrow design-time coupling between services, coupling
subdomains are grouped into a service. The amount of design-time coupling of
each domain depends on two key factors: the effectiveness of the subdomain's
API implementation and the level of API utilization by the client subdomain. [10.]

Defining subdomains depends on having a solid grasp of the business. There


are a few important factors that need to be noticed about subdomains. Firstly,
they are models, and their main alignment should be with business concepts.
Secondly, they should be a team-sized portion and each of the entities defined
in the system operations stage becomes a part of a subdomain. Lastly, the most
important property is loose coupling and being highly cohesive between
subdomains. [10.]

4.4 Designing services architecture

The most critical part of designing microservices is defining the service


architecture. The service architecture contains services. The service is a
grouping of the subdomains defined in the previous phase; therefore, each
service contains one or more subdomains. A subdomain can only be in one
service. If executed well, effective architecture that can expedite software
delivery is achieved. Conversely, a poorly executed approach may impede the
speed of software delivery. Ending up creating a distributed monolith is the
worst scenario, an architectural anti-pattern that embodies the drawbacks of
both monoliths and microservices. [11.]

Creating a service starts by defining a name and responsibilities. For instance,


an order service contains order information and manages available delivery
time. A service includes operations and events in its API, and it depends on
other services' APIs for functionality, utilizing their operations and events as
necessary. (See Figure 5.) [11.]
16

Figure 5. Diagram explaining a service architecture. Copied from Richardson


(2023) [11].

In a microservice architecture, an API Gateway serves as a central access point


for multiple services. It manages incoming requests, handling tasks like
authentication and authorization, and routing them to the appropriate service.
Additionally, it may facilitate API Composition, combining multiple services to
fulfill a request. The main purpose of the service architecture is to deliver the
system operation. The collaboration between the services and the API is the
implementation of the operation. This collaboration relies on various design
elements such as API operations, event publication, proxies, and event
handlers. The method of invoking system operations includes HTTP requests to
the API Gateway, messages published to channels, or scheduled tasks. [11.]

System operations can be categorized as local or distributed. Local operations


involve subdomains within a single service, while distributed operations span
multiple services. Collaboration for local operations is straightforward, whereas
distributed operations require more complex patterns. Operation realization
refers to the subset of the architecture dedicated to implementing a specific
operation. It consists of services containing the operation's subdomains and
17

related elements. This concept is crucial for incrementally designing the service
architecture, focusing on one operation realization at a time. [11.]

4.5 Evaluating and refactoring the microservices architecture

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:

• System operations: Adjusting collaboration patterns.


• Services: Reorganizing subdomains among services.
• Subdomains: Dividing or merging subdomains.
• System operation specifications: Modifying to minimize runtime
coupling.

The outcome of these refinements is an enhanced microservice architecture.


[12.]
18

5 Implementing restructuring from monolith to microservices

Vahterus is a manufacturing company designing and producing heat exchanger


machines. Vahterus’s mission focuses on creating sustainable and reliable heat
exchanger solutions. The flow to create a heat exchanger starts from the
customer and the sales department. Vahterus’s heat exchangers are custom-
made for each customer and each situation. The process of designing and
producing a heat exchanger begins with a customer reaching out to a sales
engineer. Customers communicate their requirements and the specific
circumstances surrounding their need for a heat exchanger to the sales team.
Subsequently, the sales engineer initiates the process of configuring, pricing,
and quoting the heat exchanger solution tailored to the customer's needs. The
process of configuring, pricing, and quoting at Vahterus is facilitated through an
internal application known as CPQ (Configure, Price, Quote). [14.]

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.

The previous version of CPQ is a monolithic architecture application receiving


complaints about the performance from the sales department. Discussions have
taken place between the developer team and management, leading to the
decision to restructure from a monolithic architecture to a microservices
architecture. This decision aims to improve performance and prepare for future
scaling.
19

5.1 Planning

Planning is a crucial phase to start the process of transition from a monolithic to


microservices. The planning stage starts with delving into the previous
monolithic architecture in order to specify its current disadvantages and future
weaknesses for the development of the company. Furthermore, understanding
the challenges of monolith architecture assists in the process of selecting
microservices as a new architecture solution.

5.1.1 Current monolith architecture challenges

As mentioned above, the monolithic CPQ experiences various complaints from


users about its performance. After further investigation, numerous issues have
been found regarding monolithic architecture.

Firstly, the first issue discovered is overlapping business domains. As motioned


above, CPQ has a service for API integration for customers. In the monolithic
architecture, the API integration is inside the same backend as the internal one.
Although API integration does not involve the internal pricing logic, since they
operate within the same backend service, updating the internal pricing logic
requires stopping the backend and starting a new deployment. This affects the
clients using the services since providing API integration for a third party
requires stabilization. Another issue arises when a new internal feature is added
to the backend and fails to function as expected, leading to a breakdown in the
backend. This breakdown consequently impacts the API service since it
operates within the same backend infrastructure.

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

requires developers to spend a significant amount of time investigating and


testing potential impacts.

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.

In conclusion, using the monolithic architecture in CPQ results in numerous of


disadvantages. It affects the developing as well as the scaling process.
Therefore, shifting to another architecture in order to solve the challenges is
necessary.

5.1.2 Needs of microservices

Transitioning to a microservices decision needs to be thoroughly considered


[15]. In a discussion among the developer team and management, a decision
21

has been made to restructure the CPQ from monolith architecture to


microservices.

Firstly, since microservices contain independently deployable services, they can


solve the overlapping problems of the business domain. The API service can be
divided into an independent service, it does not have to be included in the
backend. Therefore, developing the internal features does not interfere with the
integration API service. Services are independent which results in the stability of
the API service as the incident of the internal services does not affect the API
service. This improves the performance of the integration API service for
customers.

Secondly, each business domain is divided into separate services to improve


various issues. Developing new features belonging to each business domain
becomes straightforward. The services are designed to be loosely coupled;
therefore, changes made in one service have limited effects on other services.
As a result, developing new features is less complicated and time-consuming
for developers. Developers do not have to spend time investigating and testing
potential impacts on other services.

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.

Lastly, shifting to microservices ensures flexibility scaling. Separating the


configuration heat exchanger to an independent service requires a normal
virtual machine to host. Since REFPROP is a single thread, scaling ten normal
22

virtual machines is more financially beneficial than ten powerful virtual machines
served for a small business purpose.

In conclusion, restructuring from a monolith to microservices is an essential


decision. Microservices offers benefits required for the growth of CPQ, ensured
the future development, and scaling.

5.2 Designing microservices architecture

Design microservices architecture is an important phase in the process of


restructuring into microservices. This phase consists of the process of
evaluating system operations and separating the monolith service into
microservices. The expected outcomes of the phase are defining business
domains, creating subdomains, and grouping cohesive subdomains into a
service.

5.2.1 Evaluating system operations

Evaluating system operation is the process of defining business domains from


the requirements of the application. The start of the user journey in the CPQ is
the configuration of a heat exchanger process. The configuration process
includes creating and managing offers, positions, calculations, and config heat
exchangers. In this phase, users are able to create, update, duplicate, and copy
offers, positions and config heat exchanger machines. Users are expected to
save offers, positions and config heat exchanger machines and get the data.

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

In this stage, selecting an additional document attached to the offer is a


required functionality.

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).

Figure 6. Diagram summarizes system operations discovery.

5.2.2 Dividing monolith service to microservices

Subdomains need to be defined in order to create services since each service is


a group of one or multiple coupled subdomains. The first subdomain defined is
24

offer management. Offer management has functionalities such as creating,


deleting, duplicating, updating, and creating children offers called revision inside
a parent offer. The second subdomain created is position management. This
subdomain is responsible for creating, deleting, duplicating, updating, and
copying the position to another offer or revision. The third subdomain is
calculation management. Similar to offer and position subdomains, calculation
management consists of creating, deleting, duplicating, updating, and copying
to another position. As mentioned above, an offer contains one or more
positions, and a position contains one or multiple calculations. As a result, these
subdomains are related to each other. Fetching the data of an offer requires
data on the positions in that offer, similar to positions and calculations.
Consequently, these sub domains are grouped into a microservice called ORP
service (see Figure 7).

Figure 7. ORP service.

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).

Figure 8. Heat exchanger service.

In the quoting phase, to export necessary documents for customers, there is a


document service. This service retrieves data from offer and heat exchanger
services, and then formats it into a PDF file with the company's branding. This
service has a separate database for saving the data for the heat exchanger
document. Additionally, offer PDF or technical drawing files are saved in Azure
Blob Storage (see Figure 9).
26

Figure 9. Document service.

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 Implementing restructuring from monolith to microservices

After decomposing the monolith architecture as well as designing


microservices, implementing them is the most important phase. The
implementation process happens in the frontend, backend, infrastructure, and
cloud.

5.3.1 Frontend

While it is common practice to implement micro-frontends alongside


microservices, the developer team has discussed and concluded that micro-
frontends are unnecessary in this case, as the front end is not complex. Besides
updating the UI accordingly to a new design to improve user experience, the
changes in the frontend parallel to the implementation of microservices are API
clients. Specifically, dedicated API clients are utilized to communicate with each
microservice individually. The frontend was built using in the React framework
with Typescript.

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.

Nest is a framework designed for creating efficient and scalable server-side


applications using Node.js. It is written in modern JavaScript and is developed
primarily with TypeScript, ensuring compatibility with both TypeScript and pure
JavaScript environments. Nest provides support for multiple built-in transport
layer implementations, referred to as transporters, responsible for facilitating
message transmission among various microservices. Microservices in the
backend use the TCP transport layer to communicate with each other. Firstly, it
is necessary to instantiate a microservice by using the create() method of the
NestFactory class (see Listing 1). [17.]

async function bootstrap(): Promise<void> {


dotenv.config()
await migrate()
const app = await NestFactory.create(AppModule)

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()

Listing 1. Instantiating a microservice.


29

The request-response message style is beneficial for exchanging messages


between different external services. To implement a message handler following
the request-response paradigm, it is important to utilize the
@MessagePattern() decorator from the @nestjs/microservices
package. This decorator is applied within controller classes, as they serve as
the entry points for the service as Listing 2 shown. [17.]

@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)
}
}

Listing 2. Message handler inside a controller.

Each service has an independent database using PostgreSQL which is an


open-source object-relational database [18]. Synchronizing types among the
frontend, backend, and database is done through a library for type declaration.
This library ensures the type is synchronized as well as prevents mismatch type
errors. This library contains a data transfer object type for data fetching between
the frontend and the backend. Enums for configuring heat exchanger data are
declared in this library to guarantee the correct type in both the frontend and
backend. As a result of type synchronizing, the process of calculating output
heat exchanger configuration is correct.

5.4 Infrastructure and cloud

Each microservice is containerized, which involves packaging each service


along with its dependencies. Containerization enhances the deployment
process and enhances security by isolating different functionalities from
hardware dependencies and other software components. Containers have the
flexibility to run on various operating systems. In addition, they are separated
30

from hardware and software objects. As a result, containers are versatile tools
for building applications. [18.]

After being containerized, services are transferred to Kubernetes. Kubernetes,


often referred to as K8s, is an open-source platform designed to automate the
deployment, scaling, and management of containerized applications.
Kubernetes is a suitable choice for automation deployment because of its ability
to self-heal. Kubernetes restarts failed containers, replaces, and reschedules
dead nodes resulting in ensuring the performance of the application.
Kubernetes facilitates the automated release of changes without disrupting all
instances, and it reserves them if errors occur. It enables updating secrets and
configurations without rebuilding the image and exposing secrets in stack
configurations. [19.] These advantages of Kubernetes make it a suitable option
for CPQ. The application is hosted on the Azure cloud. A CI/CD pipeline is
added through GitHub Actions to automation deployment.

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

department. Before, it took two or more weeks for a new developer to


thoroughly understand the monolith code base; now, it takes one week to
understand the service they will develop. As a result, new features finish one
week sooner.

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.

Overall, the main purposes of this restructuring process were achieved.


However, since CPQ is an ongoing project, updates will happen. Pricing is in
consideration to be separated into an isolating service. Testing is ongoing with
internal users; feedback is reported to the team for improvement. There is still
room for updating and developing in this project.

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.

Subsequently, the microservices concept was presented as well as the history


of it. The advantages and disadvantages were discussed since having
knowledge about the microservices was crucial for the decomposing project.

The process of designing microservices was presented next. The process


started with evaluating the need for microservices, discovering business
domains, and defining subdomains. After that, the design services architecture,
evaluation, and the refactor process were introduced. Utilizing the presented
theory, the author illustrated the process of restructuring a monolithic
architecture into a microservices project. Every stage of the process was
explained as well as the reason for the options made during the project. The
outcomes of and feedback on the project were positive. The main goals set in
the beginning were achieved.

In conclusion, the future of the microservices architecture is bright because of


its concept and flexibility. Embracing a microservices architecture enables
enterprises to adapt to evolving business requirements, deliver software more
efficiently, and remain competitive in today's dynamic market landscape.
33

References

1 Chandler, Harris. 2022. Microservices vs. monolithic architecture. Online.


2022. Atlassian. https://www.atlassian.com/microservices/microservices-
architecture/microservices-vs-monolith/. Accessed 31 March 2024.

2 Microsoft. 2006. Three-tier application model. Online. 09 November 2006.


Microsoft. <https://learn.microsoft.com/en-us/previous-
versions/office/developer/server-
technologies/aa480455(v=msdn.10)?redirectedfrom=MSDN/>. Accessed
31 March 2024.

3 Newman, Sam. 2021. Building microservices, 2nd Edition. Electronic


book. O'Reilly Media, Inc. Accessed 31 March 2024.

4 Richardson, Chris. 2018. Microservices patterns. Electronic book. Manning


Publications. Accessed 1 April 2024.

5 Richardson, Chris. 2015. What are microservices?. Online. 2015. Kong.


<https://microservices.io/>. Accessed 3 April 2024.

6 Newman, Sam. 2019. What are microservices?. Electronic book. O’Reilly


Safari Online. Accessed 3 April 2024.

7 Foote, Keith. 2021. A brief history of microservices. Online. 22 April 2021.


Dataversity. <https://www.dataversity.net/a-brief-history-of-
microservices/>. Accessed 3 April 2024.

8 Newman, Sam. 2019. What are microservices?, 2nd edition. Electronic


book. O’Reilly Safari Online. Accessed 3 April 2023.

9 Richardson, Chris. 2023. Assemblage overview: part 1 - defining system


operations. Online. 27 July 2023. Kong. <
https://microservices.io/post/architecture/refactoring/2023/07/27/assembla
ge-overview-part-1-defining-system-operations.html>. Accessed 4 April
2024.

10 Richardson, Chris. 2023. Assemblage overview: part 2 - defining


subdomains. Online. 14 August 2023. Kong. <
https://microservices.io/post/architecture/2023/08/14/assemblage-
overview-part-2-defining-subdomains.html>. Accessed 4 April 2024.

11 Richardson, Chris. 2023. Assemblage overview: part 3 - what's a service


architecture?. Online. 19 September 2023. Kong. <
https://microservices.io/post/architecture/2023/09/19/assemblage-part-3-
whats-a-service-architecture.html>. Accessed 4 April 2024.

12 Richardson, Chris. 2023. Introducing assemblage - a microservice


architecture definition process. Online. 09 February 2023. Kong. <
34

https://microservices.io/post/architecture/2023/02/09/assemblage-
architecture-definition-process.html>. Accessed 4 April 2024.

13 Microsoft. 2022. Microservices assessment and readiness. Online. 19


September 2022. Microsoft. <https://learn.microsoft.com/en-
us/azure/architecture/guide/technology-choices/microservices-
assessment>. Accessed 4 April 2024.

14 Vahterus. 2024. About us. Online. 2024. Vahterus. <


https://vahterus.com/company/>. Accessed 4 April 2024.

15 Newman, Sam. 2019. Monolith to microservices. Electronic book. O'Reilly


Media, Inc. Accessed 8 April 2024.

16 Tanner, Lindsey. 2019. TanStack router. Online. 12 January 2019.


TanStack. <https://tanstack.com/router/latest>. Accessed 8 April 2024.

17 Nest. 2023. Microservices. Online. 2023. Nest.


<https://docs.nestjs.com/microservices/basics>. Accessed 8 April 2024.

18 Google Cloud. 2021. What are containerized applications?. Online. 2021.


Google. <https://cloud.google.com/discover/what-are-containerized-
applications#section-1>. Accessed 8 April 2024.

19 Kubernetes. 2024. Kubernetes. Online. 2024. Kubernetes.


https://kubernetes.io/. Accessed 8 April 2024.

You might also like