Microservices have become a common design pattern for splitting up and modularising monolithic applications. The indiscriminate application of this particular design pattern is quite a bit worrying, though. A few months ago I gave this answer to the question what the biggest struggle with Microservices is:
Convincing people that microservices are not a cure-all but just another design pattern.
You have to start out with a monolith and only if you realise along the way that some components might work better as a service (micro or not) you should extract those. Until then, commonplace modularisation will serve you just fine.
Once you have more than 1 microservice running infrastructure becomes a huge problem. There’s no real turnkey solution for deploying and running internal / on-premises microservices yet. You basically have to build monitoring, orchestration and logging infrastructure yourself.
Design patterns are an excellent tool. Microservices can be a useful design pattern if used under the right circumstances and if applied to the problem they were meant to solve. If applied haphazardly though they tend to do more harm than good. At best your application will become more complex to maintain and operate. Worst case, you’ll end up with a distributed monolith.
Anyway, even with use cases amenable to Microservices what we often see is decoupled services on the back-end / server side of an application yet a rather tightly coupled, perhaps even monolithic front-end / client consuming and tying together these back-end services. This arguably offsets some of the benefit obtained by introducing Microservices: If we have a monolithic, feature-rich client that contains a lot of business logic and knowledge about independent Microservices anyway what’s the point of having these Microservices in the first place? In that case don’t independent, single-purpose services just add overhead without providing any gains?
This argument does have a point and this is where ideas like Self-contained System (SCS) and the less unwieldy term Micro Frontends (which essentially means the same thing) come into play. These concepts argue in favour of extending the idea of Microservices to the front-end / client.
There are several different approaches for achieving this such as lazily loaded Angular 2 / 4 modules or web components and Custom Elements if we want our distributed applications to remain both framework-agnostic and future-proof.
While there’s some merit to this idea it should also come with a stern warning: “Don’t build a distributed client / Self-contained System / Micro Frontends unless it absolutely makes sense!”
Not only will applying these design patterns incur additional overhead on top of the one that already comes with Microservices but if these patterns somehow end up being the ‘new normal’, the default way for creating web apps (as already and unfortunately seems to be happening with Microservices) we’ll be in deep trouble. By indiscriminately using complex front-end frameworks creating web applications today often already is made much more difficult than necessary. In many cases Micro Frontends would only pile on top of that.
Another aspect to consider is this: With websites that are located more on the dynamic / feature-rich app rather than the content-centric / document end of the web app continuum we want consistent design and user experience and a coherent user journey. Although this is possible with distributed client applications as well it becomes much more difficult. Instead of simple event-based behaviours at the very least we’d have to make use of a distributed message bus in order to inform other parts of the application when the state of an application component elsewhere has changed.
So, if after careful consideration you decide to apply the Self-contained System or Micro Frontends design patterns in your application architecture by all means do but keep in mind that doing so will come at a cost.