How / When to use shared libraries in Microservices
One of the advantages of Microservices architecture is that it enables loose coupling between components / services. The deployment independence is important as it brings true agility and reduces communication overhead among different teams and services.
Shared libraries make Microservices tightly coupled and introduce tight dependencies. When we make a change, we need to ensure that it does not break another service that depends on the shared library.
This requires communication between multiple teams. Also, change in a shared library leads to all the services that depend on it to be redeployed. This leads to long build, release, deployment times and coordination which defeats the one major purpose of going with microservices.
We might have to consider the order of deployment of several services as well. All this leads to more synchronization and communication among teams. So, it is recommended that in Microservices architecture teams should avoid using shared libraries. Really? move on to next section
Manage the Shared Libraries — The “polarity way”
While microservices architecture enables more developers to work independently from each other, breaking things up introduces new obstacles. This complexity also slows down development.
It creates the need to resolve the same types of problems every time a new service is added to the architecture.
How to handle this?
Now we have to decide how to handle the situation. What third-party libraries should we use? What’s the right interface? How much should be tested?
This is a cost incurred by every team that is forced to spend time implementing redundant solutions to cross-cutting concerns instead of solving the primary issues for that service.
One possible solution is to use common internal shared libraries across microservices. This approach enables teams to share solutions to common problems while retaining the autonomy to use custom solutions where needed.
Decide the right candidate for Shared Library
You want to reuse a critical technical logic / snippet that can’t have its own independent life cycle. They typically don’t change depending on the business need. Let’s take a couple of examples to understand this point.
- An HTTP client library to talk to core services. It adds retry logic, timeouts, ,exception translation etc. We don’t want all our services duplicate this logic. It is better to abstract this logic in a shared library which is maintained by the platform or shared libraries team.
- I prefer to use a library that all services use to return success and error response in a consistent format and structure based on our internal requirements / design with appropriate status codes
- An extensible validation library.
- An wrapper around third party libraries / low level APIs
The Decision Tree
Shared libraries if done well and for the right reasons do not introduce hard dependencies that we want to avoid in Microservices architecture. Instead, extracting out such common code into shared libraries can speed up development of new services