There are already many great articles about good and bad microservices design. There is also an enormous amount of bad articles showing the bad design of microservices as a pattern. And a huge amount of teams who fell into that trap. The truth is: You may not need microservices, this is not a silver bullet. But you definitely need modules.
Here are some arguments for microservices I’ve heard too many times.
Microservices are simple and “lightweight”
No! This is one of the most complex architecture patterns next to distributed actor system and leader election with the Paxos algorithm. Microservices make everything harder: deployment, monitoring, tracing, debugging etc. Also, the HTTP layer between modules introduces latency and overhead (serialization/deserialization, network etc). Microservices will be slower and when you add-up CPU and memory, the system will be heavier than “the monolith”.
I need microservices for modularization
No. You need any programming language with built-in support for compilation units, packages etc., or static code analysis/testing for that (ArchUnit). Learn abstraction, encapsulation, facade, loose coupling, cohesion on modules/packages first. Also, your microservices should be modularized further and I don’t mean entity/DAO/service/controllers. These are layers.
I need product service, user service …
Nope. You haven’t watched the DDD video till the end. This is the “hello world” problem of microservices (the Greeter Service). There is no microservice-per-entity pattern. You don’t want to use the same service for e-shop search, manufacturing, package design, warehouse, invoicing, rating and shipment. These are separate domains where “a product” may have different meanings and different attributes.
Maybe these domains are good candidates for microservices…
I need microservices to scale-out
Or you can just run multiple instances of your well-designed modular monolith and successfully scale-out. Keep it stateless (or enable sticky session on the load balancer) and it should do the trick.
I need to handle different vectors of changes
Well, for this you need modularisation and automated testing. Http between modules does not help here, does it? A group of developers can implement features in different modules without interrupting each other with git and branching strategies. Have you heard about the “monorepo” approach for microservices? Sounds like coming back to monolithic development/integration feedback loop.
Everyone does it
It does not mean that everyone is happy with it. If what you have is a hammer, everything looks like a nail. Do you have the same problems as Netflix or Google? Even Netflix finds out that they could have done some things better. Watch their blog.
Do you want me to create monoliths then?
A monolithic system for the product manufacturing process, assembly, shipment, supply chain, sales and invoicing is probably not the best design. But does each of these elements has to be a separate microservice? I want to encourage you to think about modularization. You definitely need modules, but maybe only some of them need to be microservices. Or at least be prepared that some of them may become ones.
Think about what problems do microservices solve? The same as SOA did years before but with better tooling. It is developer-driven rather than a vendor-driven approach to services architecture in large organizations. Decoupling monoliths with ESB at a heart of the system just moved the whole complexity into ESB making it a monolithic ball of wool. With microservices and APIs, the IT industry is running away from SOAP and ESBs.
Think: Do I have such problems?
Modules have different scaling characteristics
In general, you don’t need microservices to scale out. But when one part of the system (e.g. customer-facing) need to scale out much faster than another part (e.g. invoicing) then microservices looks like a good idea.
You need releases at a different frequency
Features in e-shop need to be released into prod 3 times a week/a day, while invoices have not changed for over a year. This looks like a microservices situation. Rolling back unfortunate releases will be easier.
I need to support multiple domains
Your stakeholders speak different languages — they use the same words that mean different things or use different words for the same concept. They come from different business areas and have different goals. Finance, sales, manufacturing, etc.
You need to use the right tool for the job
Adding every library from the last 2 epochs of IT history may not work. Sometimes you need to have physical/process separation of systems that use different tools. Like video processing, OCR, data stream processing, ML, IoT etc. Sometimes there are better tools for a job in Python, Scala, Go etc. Just use wisely.
You have different security/privacy/reliability requirements for modules
A piece of the system that is much more critical than the rest of ita may be a good choice for a microservice with some more aggressive testing strategy, release window, DR procedures. Also having failure isolation will prevent the whole system from going down (the “bulkhead” pattern).
A piece of the system that handles sensitive data (e.g. storing credit card numbers will require PCI DSS compliance) may have additional protection means that usually comes at additional cost and reduces flexibility. It is a good idea to limit it to a dedicated microservice.
You need multiple teams working on your system
By multiple teams, I don’t mean 2x3 people. I’ve seen 5 people working on 12 microservices — it didn’t work. Up to 20 devs can work on a well designed modular monolith. With 50 it will be challenging. With microservices, you can limit the amount of code new developers have to get familiar with. Also, some of the microservices might have slightly different frameworks or conventions.
If you find out that you need to release the whole system of microservices together, what you’ve built is a “distributed monolith”, which is the worst kind of it.
The anti-corruption layer is needed
ACL is a special kind of microservices that do not serve a business/domain role but they run as a proxy to external or legacy systems. Sometimes translating protocols, sometimes being a circuit breaker. You may need to pull data from a mainframe system or send some data over SOAP, FTP file or integrate with ESB. You may have very strict requirements to connect to a partner infrastructure (IP filtering, mTLS, strange authentication patterns). Such an adapter microservice will help.
Links from “My bookmarks” still valid in 2020:
Originally published at https://www.linkedin.com.