Yet Another Blog Post on Microservices!
As you know, microservices have been a popular concept for nearly a decade in the IT sector. Many companies have applied this concept so far. Some say it is a silver bullet, and some say it is just hype. We have also been using this concept successfully for over four years in my company and have gained lots of experience. Now, I will give you my personal thoughts on this topic.
Agility and Microservices
As you all know very well, the opposite of microservices architecture is monolithic architecture, but what do we achieve by applying microservices architecture instead of monolithic architecture? The answer is agility. As an application built in monolithic architecture grows, it becomes more and more cumbersome every day. Microservices architecture lets you scale parts of your application independently, and you can manage your application and sustain agility while growing. But microservices architecture is just a part of the bigger picture and is not enough alone. As I mentioned previously in the post “Why We Need Agility” if IT companies can break down their business into products as Domain Driven Design (DDD) suggests, build small agile teams that develop those products as loosely coupled microservices and manage those services using DevOps practices, only then they can take the real advantage of agility in their business.
It’s a Matter of Need
So everyone wants to be agile, should everyone switch to microservices architecture? Not exactly. Microservices architecture is not a silver bullet, it comes at a great cost. Managing a microservices architecture is a lot harder than managing a monolithic architecture. You should build the right infrastructure, scale your system carefully, and watch your system for errors continuously, and that costs you extra time and money. So there is a threshold here. Before deciding on the right architecture, you should first ask yourself, do I really need that much flexibility, scalability, and agility? For small companies and applications which aren’t expected to grow extremely, monolithic architecture may be better to be chosen over microservices architecture.
Let There Be “Domain Driven Design”
After choosing to continue with microservices architecture, you should examine and figure out your domains with the help of Domain Driven Design (DDD) principles. This may be the most important part. If you can’t separate your domains wisely, believe me, you will suffer a lot. Anyone who applies microservices architecture has to understand DDD principles perfectly.
While designing microservices architecture, you should always keep in mind that each microservice should be well separated from others as if they are different applications of different companies. Microservices may be written in different programming languages. They may use different database types. Each microservice may be developed by a different team. They are completely different things.
After your design,
- If you are sharing data between microservices, review your design.
- If you are calling another microservice to get data, you should consider copying that data into your database instead (t-1 or near online).
- If you are creating a distributed transaction between microservices, also review your design.
I know there will be times that you simply can’t avoid some of them, but it is more likely that you made a design mistake if you have one of the above.
Technical Infrastructure
If you develop in microservices architecture, you will need a better understanding of DevOps principles. You should build a complete CI/CD pipeline which includes continuous integration, continuous delivery, and continuous deployment. You should prepare a logging infrastructure and keep track of your entire system via your monitoring infrastructure and alert mechanisms continuously. You should also prepare a messaging queue system (Rabbit MQ / Kafka etc.) to provide asynchronous communication between services. You may also consider having a caching mechanism (Redis, Memcached, etc.) for performance improvements. As you can see, there are so many steps to do before having a fully functional microservices architecture.
Designing Fault-Tolerant Systems and Preventing Single Point of Failures
In a distributed system, there are so many ways a fault can occur, and believe me they will occur. Machine node problems, disk problems, network problems, and firewall problems can occur at any time and your service instances may become unreachable or slower. If you don’t design fault-tolerant systems, a single point of failure can occur and it can break down your whole system. You have to think of worst-case scenarios while developing, and you have to handle all of them.
You should,
- Do a load test before deploying services in order to set instance count and memory limit properly,
- Use circuit breakers to handle unresponsive services,
- Use rate limiters to prevent heavy loads over your capacity,
- Set timeout values to each of your services,
- Set retry policies where possible,
- Set TTL values for caches,
- Use distributed locks to prevent conflicts between instances,
- Use compensation strategies for transactions,
- Design highly available and eventually consistent systems,
- Monitor your system metrics and set alerts on proper threshold values
These are the main points that you need to understand well before starting your microservices journey. I hope this post helps.