Microservices design considerations
Microservices movement has started, now no one wants to maintain big monolithic systems and everyone wants to build small interconnected systems for faster development, reusability, and reduced blast radius. In this blog, I am going to discuss various design principles for implementing microservices.
Single Responsibility Principal
A microservice should have single responsibility so that it will be easy to maintain and be reusable. When the microservice has a single responsibility, we can easily choose the best way to implement it to accomplish that particular responsibility.
Being Stateless is a very important design principle for the modern applications which needs to scale on demand. The main idea behind breaking the complex application into multiple microservices is that they need to scale independently so while designing microservices we need to make sure that they are stateless.
Microservices are exposed using an API so the underlying programming framework used, may be different for different microservices. It is definitely great flexibility but if we are not cautious then we may end up using too many frameworks and it might be unmanageable as it increases deployment cost by having to write and maintain different scrips for deploying different frameworks. So choose only a couple of programming frameworks which suits your needs.
Microservices implementation can go wrong in many ways if we don’t have proper data classification and segregation strategy. Whatever may be the underlying technology to store and retrieve the data, make sure to classify the data as Critical, Confidential, Internal and Public. This classification helps to segregate data access controls for each microservice in order to reduce the blast radius.
In case of failures or security vulnerabilities there might be data loss or leakage so give only required data access to a particular microservice.
Microservices might require access to various resources like databases, file servers, and third-party services. Credentials are required to access these resources and how are we going to manage these credentials? Copying credentials in each microservice pose a serious security risk and also when we rotate credentials, we need to change in many services. It is recommended to create a few microservice to manage and distribute these secrets other services. Also if possible abstract underlying data stores by using few microservices as data providers.
Understanding how each microservices depend on each other is important to achieve better performance and reliability. The dependency graph clearly shows which microservices are critical and based on that we can define SLAs for each microservice.
We can deploy dependent microservices together or closure to each other in order to reduce latency. The dependency graph determines in which order they should be deployed and in case of failures, this will help to fix the affected services much faster.
Microservices talk to each other using API and overtime API will change and it may not be possible to make changes to all the dependent microservices at once and we need support backward compatibility so make sure you have thought about versioning of API from the beginning.
Microservices can be run on both containerized and non-containerized environments, but containerized environments better suits for microservices deployments. The number of microservices will increase as time progress, and we will need to run multiple microservices on a single server or cluster of servers. So we need to scale hybrid workloads, Containerized environments give better control over how they should scale and how much computing capacity each microservice should consume etc.
Please note: Running microservice inside containerized envionments, is a recommendation only but not an absolute requirement.
Service endpoints of each microservice should easily discoverable and reachable by other microservices. Using qualified domain names as service endpoints instead of hostnames or IP addresses is recommended, as hostnames and IPs might change. Also, keep API documentation in a common standard for every microservice, this helps in discovery and integration.
Automated monitoring and alerting is very important for microservices implementations. Usually, in the microservices implementation, there will be many things to monitor and it will be difficult to monitor them manually so we need to define key metrics and important error conditions for each microservice and set appropriate automated alerts as per your business needs.
Debugging microservice at times can be very challenging hence having right Log management process is key. Make sure you follow common logging across each microservice so that you can identify issues faster. Also, it is important to use centralized logging for analysis and debugging.
I have discussed some of the considerations for designing microservice based on my experience. I hope this will help you and I love to hear comments or suggestions from you.