Building scalable software systems using microservices
By: Lefteris Karageorgiou
Tags: Software Architecture, Software Engineering, Software Systems, Microservices, Microservice Architecture

by Lefteris Karageorgiou, Senior Software Engineer, The Signal Group

Microservices have been around for many years and have gained popularity as it is one of the most preferred architectures for building scalable software systems. At Signal Ocean, in the last few months, we have initiated a new project to create and move many of our applications to Microservices to gain several benefits that I’ll discuss in this article.

What is the Microservices Architecture?

Microservices is an architectural style for developing software applications as a collection of independently deployable, small, modular, and loosely coupled services that communicate with each other with lightweight protocols and serve a business goal.

This definition reminds us of the Unix operating system:

The Unix philosophy emphasizes building short, simple, clear, modular, and extendable code that can be easily maintained and repurposed by developers other than its creators.

Ken Thompson — designed and implemented the original Unix operating system (~1970)

According to Google trends, the popularity and adoption to microservices has increased since 2014, when author Martin Fowler began using the term in some of his publications.

One of the earliest adopters of microservices was Netflix, back in 2014, as the company could not handle the increase in the load it kept having in its system. Since then, many companies, including tech giants Amazon, Uber, eBay, and others, have embraced microservices.

Microservices Characteristics

Based on the definition of the microservices, they should share some common characteristics:

Each service is deployed independently

Each service is responsible for its own domain

for its own Each service has its own persistence

Services are loosely coupled

Rapid deployments of services

of services Communication between services is synchronous or asynchronous

To get the most out of the microservices, teams should also be separated and organized in a way that each team is responsible for their services.

Microservices vs Monolith

The Monolithic Architecture is often the default option when building applications as it is the best option to progress fast. A monolith is usually built as a 3-Tier architecture, consisting of a UI, business logic and data access layer that interacts with a database. This architectural style has been a particularly good choice for applications that do not have large complexity or big data to handle and many successful companies started their business based on a monolith. However, nowadays, the complexity and data become larger and larger and a monolith can hardly keep up with this increase due to its limitations in modularity and scalability.

This has led many companies to move to microservices and take advantage of their benefits:

Make use of latest technologies and use any technology stack

Separate the scope (business logic, domain-model)

Easier for new developers to understand the codebase

Improves fault isolation

Continuous deployments

Horizontal scale — run multiple copies of each microservice

Vertical scale — separate the scope even more based on factors

Leverage the Cloud

Create stateless applications

Transition to Microservices at Signal

Some factors that led Signal to microservices was to separate the scope of large monolithic applications, make use of latest technologies, do continuous deployments, and improve the scalability of the system.

Separate the domain model

One of the most important characteristics to successfully transition to microservices is to understand the boundaries of the domain-model of your system. Usually, the domain-model in a complex system, which consists of many applications, is huge and it is extremely hard to separate it based on business capabilities. This was also the case for Signal’s domain-model which comprises numerous applications.

The technology division of Signal has multiple teams that are responsible for a specific part of the domain-model of the system that needs to be shared among other teams. Each team is responsible to identify how to fragment their domain models by separating and isolating the database entities and creating microservices in a way that enables them to work without having to constantly switch to other microservices contexts. Each microservice created is small, modular, and exposed REST APIs for internal and external usage.

Latest technologies and the Cloud

One of the benefits of migrating to microservices at Signal was that we could make use of the latest technologies. Signal uses several languages for the backend applications (C#, Python, Java, Go) which are deployed in the Azure Cloud either in Service Fabric or Kubernetes.

The majority of the backend applications, which were in C# and .NET Framework, were successfully migrated to .NET Core and also new microservices were created. As an API Gateway, we took advantage of the Azure API Management which served us well due to the load balancing, security, throttling and customizations it offers to different clients. Finally, the Azure Service Fabric and the Azure Kubernetes Service were used as the container orchestration services for the microservices.

Continuous deployments and smaller codebase

Due to the size and smaller codebase of the microservices, the development has increased dramatically and as such the deliverables and continuous deployments. Each team has become more productive and can work on new features without having to affect other teams’ work. It is also easier for new developers to read and understand the codebase.

Fault isolation

One of the benefits of the microservices is the isolation of dependencies from the rest of the system. Each microservice runs in its own process and if one crashes, i.e. due to memory leak, it won’t affect the other services which will still operate normally and communicate with the microservices that are alive. The load balancer of the Azure API Management will stop sending traffic to the microservices that have crashed until they are up and running again.

Scalability

Last but not least, the most important benefit of the transition to microservices is how the system can horizontally scale, meaning that new microservices can be added to the system. Based on the load of each microservice, Service Fabric and Kubernetes can proceed to horizontal scaling by deploying new microservices in a matter of seconds. When new microservices are added to the system, the Azure API Management automatically load balances the traffic to the new microservices deployed and as such the load to the other microservices slowly decreases.

Microservices drawbacks

The transition to microservices brings a lot of benefits but we should also mention some drawbacks. The most significant drawback is that the complexity and architecture of the infrastructure has become more complicated as more and more microservices are being added to the system. This affects the increase in cost of the machines needed to run all the microservices as each microservice runs in its own process and requires dedicated memory. It is more difficult to analyze, debug and trace a service that communicates with several other microservices. Also, the network calls can fail and there may be delays when microservices communicate with each other through the network. Finally, it is harder to guarantee ACID database transactions in a distributed system.

Conclusion

In summary, a monolith might be best suited for some companies but microservices is the best solution for companies that need to scale their business, implement new changes faster, break down the system into smaller modules, improve fault isolation, use the latest technologies and leverage the power of the Cloud.

###

For more tech related articles, click here to follow Signal’s Tech Blog on Medium.

Want to join the Signal team? View our Job Openings here.