Microservices seem to be everywhere, everybody is talking about them, writing and consuming them. For a good reason, they can solve a lot of problems like scaling, high availability, independent developability, etc. But are they really THE solution to our problems? Do we always remember their costs?
One of the good things about microservices is, that they’re simple. Each one should be easy to understand even by a new person joining a team. I like the idea coming from DDD, that one microservice should match one bounded context (any other definition based on lines of code or the time required to rewrite the service I find artificial and probably leading to too much fragmentation, so increased complexity). But if previously our systems were complex and now are simple, where did the complexity go?
Of course in the integration of all services into a bigger system. The problem is, that whereas we know far better how to integrate different parts of a system within one executable, it’s still something we’re learning when it comes to integrating myriads of small services. One important topic is: how to follow execution? How to find out who might be affected if you change this one, tiny class? Of course, there are tools for managing complex integration scenarios, but is the cost of introducing them justifying going microservices?
Previously calling other parts of the system was easy, you just did it after importing the other Jar, DLL or gem. Now it’s not that simple, you need to know the endpoint, queue or other means of communication gateway of the other service. Then you probably need to take care of any issues with that other service, what to do in case of timeouts or other connectivity issues. Previously we didn’t have such problems, because it was the same executable. Also, until recently we were trying to get rid of all the code, that wasn’t business related. Now every microservice requires its own configuration, wrapping into REST services, mappers between external and internal data structures.
I’m not saying, that we didn’t have those problems previously, we had, but I have a feeling, that now more and more stuff we do is not on business features, but just about running our applications.
Testing single microservice is a dream coming true. But how do you test your services with integration with other? If your service depends on 3 other microservices how do you set up your test environment? Using real services might be difficult if they also have some dependencies. Are other teams providing “mock” implementations, that behave like real ones, but have no dependencies or requirements themselves? It takes effort and also creates a risk, that those “mocks” will not behave the same way in some corner cases.
My team is currently trying a different approach. For our product, we have created quite a few small modules with clearly defined dependencies (we follow clean architecture approach) that we, later on, combine in a larger “monolith”. Each module serves a single purpose and might be viewed as a “microservice”, but all of them are still packaged into a bigger executable and deployed as such. Each module has its own release cycle, but only the final executable module, that has no other responsibility than putting together all modules in specific versions into a working application, is being deployed when desired. I admit, we merely started with this approach, but it already proved very flexible when we were refactoring and moving code around. Of course, this is not solving all issues you might run into with microservices, it also brings back some problems from past, but currently, it works for us.