TL;DR Deploying 100 times per day is impressive, so is having 5k devs working in parallel on the same codebase, serving hundreds of thousands different API consumers around whole globe or handling fluently interest spike of several millions of new users due to world-scale news event. But there's a huge chance that these achievements are not really applicable to your problem / domain / enterprise, so don't mindlessly copy'n'paste approaches that have served the purpose of solving different issue with a silly hope that they can solve your local problems as well ...
Our whole industry suffers from being totally mesmerized by the concept of microservice & its assumed benefits: replaceability, independence (of execution, deployment), scalability, universal access, resilience, etc. As in addition it's also well aligned with other catchy terms (like Continuous Delivery, DDD or reactivity), even if no-one admits it openly, it's frequently treated as a default architectural approach for almost any back-end product, regardless of the scale, complexity, demand characteristics, ...
As a result, artificial (& unnecessary) boundaries are being introduced & all the existing logical (/ conceptual) ones get super-solidified: state becomes distributed, communication gets latency, failure may be partial ... We tend to prefer more explicit, conspicuous dissection as a supposed hallmark of good composition (yikes!).
I'm not going to blame the microservices architecture itself, it's really great, but for some particular scenarios: for web-scale solutions, high variety of service consumers (so proper API definition versioning is a key), large-scale web deployments of products developed by numerous, not co-located teams. But frankly, this is NOT a typical challenge within whole our industry.
Pick your (correct) battle
Let Netflixes be Netflixes & Googles be Googles, but in the same time think about your own (real) problems, challenges & goals. These could vary, but the usual suspects are: domain complexity, "transactionality" of operation, data safety (in case of failure), general security, architecture long-term maintainability & coherence ("tidyness"). In fact, in 95% of cases, you can achieve all of these (& majority of the ones mentioned in previous paragraphs) without implementing microservices, with:
- one solution / repository / workspace (or whatever it's called on your platform)
- one OS-level app (or several instances of the same app, that wraps all the functionality)
- one database (that still may consist of many schemas ...)
- one package (/ artifact to be deployed)
- single version (of API definition)
Sealed boundaries don't solve issues - they can make them more explicit, but for a price. In case of microservices, truly significant price, while similar effects can be achieved with ... applying SOLID practices. Modular design doesn't force multi-process split - proper composition, high independence & low coupling is within reach even with such means of development expression like namespaces, libraries, interfaces.
Simplicity. Simplicity is the key.
Don't overlook all the fiercely flashing warning signs, e.g.:
- uncontrollably growing boilerplate code
- code that's there just for the sake of being ("empty pass-throughs")
- layers (or other contracts) without a clear purpose that could be articulated by ANY dev in team
- managing system (/ convention / mechanism) for something that is always (& intended to be) singular
- dubious inter-process communication (e.g. within single machine, between the components that serve the same business function(s))
Complexity is out there (anyway)
Looking back at my whole career in software development, there was always complexity, lurking somewhere there in shadows. It was always of one of two origins (/ characters): either technical or business domain-related, and the trick was always to postpone / avoid technical complexity as long as it wasn't explicitly solving domain complexity.
Failing here meant usually getting bogged in pointless & time-consuming struggle with (usually immature or botched) technology, while in the same time really meaningful problems were put aside. Microservices (& their implementation) seem like another "perfect excuse" to do some fancy tech stuff instead of bringing real value ... Don't get tricked into that seductive path, favour simplicity instead, as it means lower inertia, higher velocity & fewer constraints.
Pic: © Jean Nouvel, "Monolith"