In this article, We’re going to cover microservices. First, We’re going to start by explaining what a monolith application architecture is, what were some of the challenges of a monolith architecture, and why the industry moved slowly towards the microservices architecture. Then we will see what microservices or microservice architecture is exactly, as well as best practices, benefits, and how the communication between microservices actually works. We will also see different ways to manage code for microservices application and talk about monorepo vs polyrepo and advantages and disadvantages of both.
What are Microservices?
Microservices is a way to architect an application by breaking it down into smaller, independently deployable, and loosely coupled services. This allows for more flexibility and scalability in development, deployment, and maintenance of the application.
When creating a microservices architecture, there are a few important questions to consider:
- How do we decide how to break down the application?
- What code goes where and how many microservices do we create?
- How big or small should these microservices be?
- How do these services talk to each other?
The best practice for breaking down an application into microservices is to base the division on business functionalities, not technical ones. For example, in an online shop application, the microservices might include products, shopping cart, user accounts, and checkout. Each microservice should do just one isolated task and be self-contained and independent from each other. This is called loose coupling.
If you change something in the payment service, you will only need to build and deploy the payment service, and nothing else will be affected. Services have their own individual versions which are not dependent on others. This means that the release cycle has to be completely independent.
To connect these isolated services, microservices communication is typically done using API calls or message brokers. Another popular option is using a service mesh, which takes over the complete communication logic. This allows for flexibility, as each service can be developed with a different programming language and have dedicated teams working on them without affecting or being affected by other service teams.
How do Microservices Communicate with each Other?
Now, if these services are isolated and self-contained, how do they connect to each other? Because obviously the payment service will need something from the user account to process the payment or the checkout service will need something from the shopping cart.
A very common way for microservice communication is using API calls. So each service has an endpoint on which it accepts requests from other services. Services can talk to each other by sending each other HTTP requests on these endpoints. This is a synchronous communication where one service sends a request to another service and waits for the response. So the user account service can send an HTTP request to the payment service on its API endpoint and vice versa.
Another common way of communication between microservices is using a message broker with an asynchronous communication. Here, services will send messages first to the intermediary message service or a broker such as RabbitMQ for example. Then the message broker will forward that message to the respective service. So again, the user account will send the message to the broker saying please pass this message on to the payment service and message broker will then forward that message to the payment service.
A third way of communication between microservices which is becoming pretty popular, especially in the field of Kubernetes, is using a service mesh. With a service mesh, you have kind of a helper service which takes over the complete communication logic. So you don’t have to code this logic into the microservices and have this communication logic kind of delegated to this external service.
So these are different communication options and since the services are all isolated and talk to each other either with API calls or using additional services, you can even develop each service with a different programming language. And you can have dedicated teams for each service that can choose their own technology stack and work on their service without affecting or being affected by other service teams. And this is exactly the most important advantage of microservices architecture compared to the monolith.
Disadvantages of Microservices:
However, these benefits come with a price. So while microservices made developing and deploying applications easier in many aspects, it also introduced some other challenges that weren’t there before when you break down the application into these multiple pieces. This introduces a lot of complexities and challenges. One of the main complexities may be configuring the communication part between the services. Because a microservice may be down or unhealthy and not responding yet, while another service starts sending requests to its API, expecting a fulfilled response. In which case, you may get unexpected results.
Also, with microservices deployed and scaled separately, it may become difficult to keep an overview and find out when a microservice is down or which service is actually down when something in the application is not working properly. So, you definitely need a proper configuration of your application setup and its pieces to make sure your application as a whole functions well. But there are various tools for making all this easier. So even though the microservices architecture is complex, there are a lot of tools and still more being developed regularly to make running microservices applications easier.
The most popular one you probably already know is Kubernetes, which is a perfect platform for running large microservices applications. Now, before moving on, I am excited to give a shout out to Hashicorp, which is a company that many of you probably already know about and has a lot of really cool technologies, many of those that actually solve various challenges when working with microservices applications. From the infrastructure provisioning tool Terraform to the secret management tool Vault, which is pretty much becoming a standard already in the industry for managing and protecting your sensitive data.
Hashicorp also has a service mesh product called Console, which helps you securely connect and observe your microservices running in any environment. So, with various tools that Hashicorp offers, you can actually provision, secure, connect, and run cloud infrastructure for your most important applications and specifically for your microservices applications.
CI/CD Pipelines for Microservices
An important element of deploying microservices is a CI/CD pipeline. In fact, there are many companies with microservices applications that deploy multiple times a day. Companies like Amazon, Google, and Netflix have applications with hundreds of microservices that they deploy thousands of times per day. So, you can imagine the complexity and the sophistication of their CI/CD pipelines.
In the modern world and workplace, you will most probably be working with microservices, and in this case, you would need to know how to configure the release process with a CI/CD pipeline for microservices. A CI/CD pipeline automates the process of building, testing, and deploying microservices. This allows for fast and efficient deployment, making it easier to catch and fix errors and bugs before they reach production. Additionally, it also enables continuous integration and delivery of new features and improvements to the microservices application.
Managing Code for Microservices Applications – Monorepo vs Polyrepo
We said that microservices is when application components get developed and deployed separately as individual micro applications. So the question is, how do we manage the code for microservices application in a git repository like GitLab for example. With one project, it’s simple. We just have one application and it gets its own git repository. With microservices application, we have two options for how the code is managed: Monorepo and Polyrepo.
Monorepo stands for single repository, which means that all the code for the microservices application is stored in one single git repository. This approach allows for easier collaboration and code sharing between the different microservices, but it can become harder to maintain as the number of microservices increases.
On the other hand, Polyrepo or Multi-repository approach, each microservice gets its own git repository. This approach makes it easier to manage and maintain the code for each microservice separately, but it can make collaboration and code sharing between microservices more difficult.
It’s important to note that both approaches have their own advantages and disadvantages and the best option for your organization will depend on the specific requirements and constraints of your microservices application.
What is Monorepo? – Advantages and Disadvantages
Monorepo or Single Repository is having one GitLab repository for all the services. So we would create one project for a Monorepo. So what’s the difference here or how do we structure multiple micro applications inside one application repository? Well, a common way is using folders. So you have folders for each service like shopping cart, payment, notifications, etc. and all the code for those services are in those respective folders.
Having a Monorepo, meaning all the services still in one repository, makes the code management and development easier because you only have to clone and work with one repository. So it simplifies things. Plus, if you have some shared code between the services like Kubernetes manifest templates, Helm chart, or Docker Compose, whatever, you can put them in the root of the project and all the services can basically reuse them.
But Monorepo also comes with some challenges as I mentioned. The most important criterion of microservices is to be completely independent and isolated so no tight coupling between the services inside the code. And it becomes easy to break this criterion when you have a Monorepo. So you have junior developers with less experience in the Monorepo setup it’s easier to make such mistakes and develop tightly coupled logic or code in your services.
Another downside of Monorepo is when the application becomes really big, cloning, fetching and pushing becomes slow because your project is huge. And in terms of the CI/CD pipeline, in most of the CI/CD platforms like GitLab CI/CD or Jenkins, you can only create one pipeline for one project. So you are building multiple services with a single project pipeline and that means you need to add additional logic in your pipeline code that makes sure to only build and deploy the service which has changed. So if you make code changes in the payment service your pipeline code should detect that and only that service should be built, tested, and deployed. It is possible to do that but it’s a little bit more challenging.
One more issue with a Monorepo is that since you have just one main branch because you have one repository. If developers of one of the services break the main branch, other services and their pipelines will be blocked as well. But there are a lot of companies including very big ones like Google who actually use Monorepo for their applications. It’s important to evaluate the specific needs and constraints of your organization before choosing the best approach for managing the code of your microservices application.
What is Polyrepo? – Advantages and Disadvantages
The second option which is probably a bit more preferred one is Polyrepo or Multiple Repositories. With this approach, for each service we create a separate git project. So the code is completely isolated. You can clone and work on them separately because they are in separate repositories.
Now, even though they are separate application repositories, they are still part of this bigger application. So of course, you would want to still have some kind of connection of these repos for an easy management and overview. And if you’re hosting your code repositories on GitLab for example, you can use GitLab’s feature of groups in order to group code for all the microservices that belong to the same application in one group to make managing those repositories easier. So, essentially, you would create a GitLab repository group for your application called “My Online Shop” and inside this group you can create a separate project for each microservice that belongs to that application.
If your company has multiple microservices applications of course, this will help keep an overview of what projects belong together but also within the group you can actually create secrets or other CI variables that can be shared by all the projects in that group. Now what about the CI/CD pipeline for a Polyrepo? Well, for Polyrepo, the CI/CD configuration is more straightforward because you just have own pipeline for each repository. So no extra logic is needed to differentiate between the services.
Now of course, everything has advantages and disadvantages. So for Polyrepo as well, you have some downsides like having application code in multiple repositories can make working on the project as a whole harder especially if you need to change two or more services at once because a feature or bug fix affects multiple services. If you need to switch between the services often this can also be tedious. Plus things like searching something across multiple projects from the code editor can be difficult or impossible. Also, in the Polyrepo, you can’t really share files in the project like Kubernetes or Helm manifest, Docker Compose and so on. You would either have to duplicate them in each project’s repository or have to create a dedicated project and reference them from there.
Conclusion: Which One is Best?
So as you see both options have their advantages and disadvantages. But the general rule is that if you have a small project with just a several microservices, you should stick to Monorepo and save the overhead of creating and managing and checking out multiple repositories. On the other hand, if you have separate teams for each service, if you want to have complete isolation, smaller code base to clone on pipelines and so on then of course the Polyrepo would be a better option. Now, I hope this gave you a great introduction to microservices and now you understand what it is and why everyone is using it. It’s important to evaluate the specific needs and constraints of your organization before choosing the best approach for managing the code of your microservices application.