How I Transformed the Tip2Go Monolithic Project into Microservices
When the Tip2Go project started to expand, we urgently needed to change its architecture. Initially designed as a small monolith, splitting it into services was an interesting challenge!
Regarding the project I've mentioned a couple of times. We are already in the final stages, and even our friends and acquaintances are using it, providing feedback that we use to make corrections or additions.
Since Tip2Go was initially conceived as a Telegram bot with limited functionality, I started building it as a monolith containing all the functionality. This is really convenient when you package everything in Docker and can deploy it with a single command.
However, as the project idea developed, I realized that keeping it monolithic would require disproportionate server power, which again means maintenance costs. So, I made the decisive choice to split the project into services that could be distributed across different servers. Fortunately, I adhered to modern programming approaches from the start, and even as a monolith, the project was very well designed internally, following the SOLID principles.
This means that necessary objects can be easily extracted from the project and quickly transferred to another project without harming the main one. The single responsibility principle, represented by the letter S in the SOLID acronym, is very important. If I had added excessive functionality to objects, it wouldn't have been so easy to separate them into individual services.
So, what does the project look like after being divided into services?
There's a load balancer at the front, followed by four services, a database on a separate server without an external IP, and files stored in S3.
It turned out that such an architecture costs almost half as much as a single server. Not to mention, this option is more flexible and reliable compared to a monolith.
In the project, only one IP is exposed, and the load balancer on it redirects requests to internal services.
If an image is requested, the request is redirected to the file service. Here, I implemented an old idea with images, specifically checking their existence on the server and returning a placeholder if the image is not found.
If a user wants to access the control panel, they must first authenticate on the main service and have the appropriate role in the system. Otherwise, the user is simply redirected to the main service page.
For the bot, which we haven't forgotten and is also part of the project, a separate service is allocated, accessible only from certain IP addresses. Otherwise, the user is again redirected, but this time to the bot launch page.
And the fourth service, which is user-facing, is open to both authorized and unauthorized users. Of course, authorized users are provided with more functionality and capabilities. However, unauthorized users still have access to all the free information available on the project's pages.
But I'll talk about that another time.