Modern Software Architectures: Microservices

In the past 10 years, a new architecture has been emerged called microservices. Even though there is no solid definition of what a microservice is, it is getting clear how to seperate a microservice from a service.

Briefly, a service provides a functionality with a public API to clients and communicate with other services over network.

In the early days of software development, any update on a service requires a whole version update with its own testing and quality assurance. This usually slows down many developers who are not relevant to the update. Also, any failure of a part of a service means failure of whole service.

Before microservices, service-oriented architecture (SOA) was a popular solution to this issue. SOA organizes apps around a business process and divides them into discrete, reusable services that communicate through a service bus. This allows services to be built, tested, and tweaked simultaneously.

Before getting into microservices, there are some terminologies we should know:

  • Vertical scaling: simply adding more CPUs and RAMs to a machine
  • Horizontal scaling: adding more machines (usually tiny and cheaper ones)
  • Stateless application: does not depend on any previous data when restarting

Microservices Arhitecture

Given the history of SOA, microservices are not actually all that new of an idea. However, it became more viable thanks to containerization technologies. We will see some characteristics of a microservice.

Keyword to define a microservice is simplicity, since it is a micro service, it should be small and lightweight enough. You will see how each characteristics are related to simplicity.

It does not matter which server or machine a microservice is running on

In the past, you write a service and run it in a single machine with so much RAM and CPU. You have to install all dependencies in that machine so that your service can run on top of that.

In microservices architecture, you should be able to deploy your service in any server or a machine. It means a microservice should be infrastructure independent. Thanks to containerization tools such as Docker and deployment technologies such as Kubernetes, we now able to set up all requirements of our service and run on any server.

It should be stateless and not store machine specific data

A microservice should be stateless so when there is an error, when you restart it or even when you deploy it to another infrastructure, it should depend on any data to run successfully.

It should be horizontally scalable

In the past, services are scaled vertically, which means to handle high traffic, they add more hardware, which is more expensive and waste of resources when no traffic. This monolithic behavior makes it hard to scale individual components of a service when a component gets higher traffic than others.

Since microservices are stateless, it does not matter if you run single or multiple instances of a microservice. So, it is easy to scale microservices horizontally and load balancing is simpler. For example on Kubernetes, it creates multiple pods to run your microservice to handle high traffic and when traffic decreases, it terminates unnecessary pods.

It should provide a small functionality with better performance

When you have a service, it often have various numbers of components that are usually irrelevant with each other. For example, on a single server, there are 5-6 different applications running, and each provides a completely seperate API and functionality. Since it is a single service, it runs on a single process which causes potential performance bottleneck in terms of response time.

However, microservices operate on a single functionality and this functionality is usually small to respond fast. Each microservice has its own server stack and seperate ports. Which means, each microservice has its own IP, hostname, port etc.

This allows us to deploy several microservices on the same machine even though each service written with different languages and runs on different runtime environments.

It provides an API to clients

When you are using a microservice, you should not be considering which language and technologies are used for that microservice.

If you are developing a microservice, it should not take much time to upgrade performance or rewrite that microservice. So, development and maintenance of a microservice should be fast.

They do not share message bus or database

When we talk about SOA, we see that different components communicate each other through a message bus to exchange data, and they use a common database to read/write data.

When it comes to microservices, it is recommended that each microservice should have its own database. So, when you have an issue on a database, it would not affect other microservices to continue working.

It should be clear what it is doing

A microservice should be clear about what it is for. When you see its name or endpoints, you should be able to understand what it is doing. It should provide clear responses with a simple format such as JSON.