Which are the conditions based on which a system should be split in micro-services and how "small" should a micro service be?
-
1I'm voting to close this question as off-topic because this is a meta question about asking the community whether we should entertain questions about heuristics. The meta question belongs on meta.stackoverflow.com – George Stocker Jun 19 '19 at 13:15
-
@GeorgeStocker you are right! I knew about the possibility to be closed when I was submitting my question. Since there is a very good elaborate answer to the question I modified the content of the question in order to re-open it – Chrysovalantis Koutsoumpos Jun 20 '19 at 14:13
1 Answers
We where implementing micro-services architecture in multiple projects and I will try to share my experience with them and how we where doing it.
Let me first try to explain how we split our Domain into micro-services. During this the criteria for how small or how big the micro-service should be will be explained as well. In order to understand that we need to see the whole approach:
Conditions based on which we split our system in micro-services:
We where splitting the micro-services based on 2 set of environments:
- Based on Production/Staging setup. This is in general how would the system run on a Production environment to be used by our customers.
- Based on Development(Developers development machine) setup. This the setup which each developer has to have on their machine in order to run/debug/develop the full system or parts of it.
Considering only the Production/Staging setup:
Based on DDD(Domain Driven Design) Bounded Context: Where Bounded Context = 1 micro-service. This was the biggest ms that we ended up having. Most of the time the Bounded Context was also split into multiple micro-services. Why? The reason is that our Domain was very big so keeping the whole Bounded Context as one micro-service was very inefficient. By inefficient I mean mostly scaling reasons, but also development scaling(having smaller teams taking care of one micro-service) and some other reasons as well.
CQRS(Command Query Segregation Principle): After splitting to micros-service per Bounded Context or multiple micro-services per 1 Bounded Context for some of those micro-services we had them split in 2 or more microservices instead of 1. One Command/Write micro-service and the second was the Read/Query micro-service. For example lets say you have a "Users micro-service" and "Users-Read micro-service". The "Users micro-service" was responsible for creating, updating, deleting and general management of Users. On the other hand the "Users-Read micro-service" was just responsible for retrieving Users(it was read-only). We where following the CQRS pattern.
The Write/Domain micro-service in some extreme cases had multiple Read micro-services. Sometimes these Read-micro-service where so small that they where just having one De-Normalized View-like representation mostly using some kind of No-SQL db for fast access. In some cases it was so small that from code prospective it would just have a couple of C#/Java classes in it and 1,2 Tables or JSON Collections in their Database.
Service which provides Domain agnostic or Static work or services
Example 1 of this was a very small micro-service which was responsible for generating specific reports in form of pdf from an html template.
Example 2 was a micro-service which was just sending simple text messages to some specific users based on their permissions.
Considering the Development Setup:
In addition to the ones for Production/Staging setup for local purpose of developing/running we needed special micro-services which would do some work in order to make the local setup work. The local setup was done using docker(docker-compose). Examples of small micro-services there was:
Database, Cache, Identity, Api Gateway and File Storage. For all this things in the Production/Staging setup we where using a Cloud provider which provides services for these things so we did not have a need to put them in micro-services. But in order to have a whole system running for development/testing purposes we needed to create small micro-services in form of Docker containers to replace these Cloud services.
Adding test/seeding data into the system. In order to feed the local development system of micro-services with data we needed to have a small micro-service which sole purpose was to call some API's exposed by the micro-services and post some data into them. This way we could setup a working development environment with predefined data in order to test some simple business scenarios.
The good thing about this is that you can use this test data setup in combination with the local development setup for creating integration and end-to-end tests.
How small a micro-service should be?
In one our cases the smallest micro-services where a couple of View/Read-only mircro-services which had only one De-Normalized View(1 Table or 1 JSON Collection) which from code prospective had a couple of C#/Java classes in it. So when it comes to code I don't think that much smaller then this would be a reasonable option. Again this is subjective view. This size can be considered as "too small" based on some suggestions around micro-service which you can read about online. We did that because it helped us solve performance issues. The demand for this data was so big that we isolated it so that we can scale it independently. This gave us the possibility to scale this micro-service/view individualy based on its needs and independently from the rest of that Domain.
Second case of a small micro-service is the html-to-pdf service which was just creating pdf documents based on specific formatted html template. You can imagine how small this subset of functionality was.
Suggestion:
My suggestion for everyone designing micro-services would be to ask the right questions:
How big should micro-service be so that we don't have situation with monolith split into multiple monoliths? This means that the size of the created micro-services would be too big and hard to manage as this was the problem for monoliths. On top of this you get the drawbacks of distributed systems.
Is that size of a micro-service going to affect your performance? For you customers the key is that the system performance is good, so considering this as criteria for micro-services system architecture could be a very valid point.
Should or can we extract some critical part of the functionality/logic in order to isolate it? Which critical logic is so important that you can not afford to have it broken or service-downtime for it? This way you can protect your most critical part of the system.
Can I organize my team or teams with this kind of micro-services architecture split?
Considering I have the micro-services architecture done and I have "n" micro-services how will I manage them? This means support them, orchestrate deployment, scale based on needs, monitor and so on? If this architecture that you came up turns out to be challenging and not manageable for your organisation or teams then reconsider them. Nobody needs an unmanageable system.
There are many more which could could lead you to the right directions but these where the ones we where following.
Answers to those questions will automatically lead you to the smallest/biggest possible micro-service for your Domain/Business. My example about micro-services size from above might now work for your case and the rules that we where using as well, but answering these questions will bring you closer to your own approach/rule to decide that.
Conclusion
The micro-services should be as small as you need it to fit your needs. The name "micro" indicate that they can be very small. Be careful to not make this a rule for all your system. The smallest micro-services are rather an exception to solve some specific problem like scaling or critical logic isolation rather then a rule for designing/splitting the whole system in micro-services of that size. If you have to many very small micro-services just for the sake of having them and them being small you will have hard time in managing them with no real benefit. Be careful how you split it.

- 2,741
- 2
- 21
- 33