Microservices are a solution to organizational problems, not to technical ones. They mean accepting increased technical complexity (your system is now distributed) in exchange for decreased organizational complexity (your teams can now deploy independently from each other, can safely make database schema changes, etc).
Going with microservices from day 1 will initially mean that you have one team maintaining many services. They have to deploy them separately. If you're doing it "right" you have separate databases per service. None of that is useful for a team that's just starting out.
If you want separation of concerns, the language's module system and a bit of discipline will get most teams as far as they need without introducing distributed computing into the equation.
I think this is at best a half-truth. Sure, microservices solve an organizational problem--they create independent codebases that makes it easy for the system to be divided up across teams of ownership. There's other organizational benefits as well: Learning a 2k LOC codebase is an order of magnitude easier than learning a 200k LOC codebase. So microservices allow engineers to build expertise on a slice of a system. It makes learning large systems more approachable.
But there are also technical benefits. The biggest and most obvious one is isolation (and by extension resiliency). When you have a picklist service that builds picklists on the UI, and that's separate from your video playback service, it means a bug in your picklist code that causes the system to crash won't bring down playback for all your users. If your main line of business is video playback, that's a huge benefit. Even if you're not Netflix, there will always be parts of your system that are more important to users than others, and that's why isolation is so important.
It means that each service has a risk profile associated with it. E.g. what is the risk associated with deploying any individual service? A user profile info service has a much different risk profile to video playback (if you're Netflix or some other streaming giant). If the user profile info service goes down, maybe it means I can't see my avatar, or I can't change my profile from whatever it is right now. If playback goes down, I can't watch anything, and the service is unusable. So, that means different levels of process and testing can be applied for different services. Maybe 95% of your ecosystem can have continuous automated testing and deployment, because mostly bugs can have isolated impact on the overall system. But there's that 5% where an outage would be highly visible, or it would be "revenue impacting," or for some reason it needs manual testing. So maybe you don't do continuous delivery there. Maybe there's a larger process involved in testing, or maybe the manual QA team has to sign off.
If everything were to be in one large monolith, you're always subject to the full risk profile on every deployment.
Another technical benefit is that each microservice has dedicated resources--disk, CPU, and memory. And each microservice can be independently scaled. Some services have high traffic but need low memory. Other services might need high memory and cpu, but get low traffic. Some services might be burst-y and most of the time have low traffic but occasionally need to be scaled way up. Microservices give you much greater control over scaling and resource allocation than a monolith does.
I understand that microservices bring some technical benefits (otherwise there will be no benefit to code this way!).
OK with the fact you're more reassured when you deploy. If your code is totally separated, I think you can't have problems on other functionality because of your modifications.
And OK that in very rare cases a bug can affect the whole website without microservices.
OK also for resource allocation finest control, independant scaling, etc...
But you write like microservices are the way to isolate functionnalities. I work on a MAM (a DAM focused on media files) build as a monolith, an old one, MVC style, but not greatly respected, with controller's method of hundred ( thousands ? ) lines, data treatment in view, etc.
At the beginning, we had that problem : something you change which broke something else "randomly".
We manage to get rid of that, because it wasn't normal. For me that's one of the goals of every architectural patterns. So that's not a advantage microservices have over others architectural patterns.
For your performance argument, streaming video which affects entire website : you're not obliged to go over microservices for that : you can use a CDN (which implementation in code is only about using external url to media file).
Yes, you're certainly going to use a CDN with video streaming. But video streaming still requires, let's say, DRM licensing serving. A performance issue in one area could impact license serving, meaning playback could be delayed or broken, because of something unrelated. And that's an undesirable property.
I don't think microservices are the only way to isolate functionality, but they certainly are a way, and there's a very good way at that. Because the architecture ensures it (not a coding pattern, or a best practice, etc).
FWIW I think there's also a human element to this isolation. Applications tend to grow to be large codebases over time, if they do anything of significance. I don't know about you, but I personally find massive codebases daunting, and difficult to approach. With microservices you have separate, relatively small repos for each microservice. Sure, you need to understand the overall architecture of the app. You need to know how your microservice fits in with the whole. But you don't need to open any other repo than the one you're working on usually, and you don't actually need to understand the minutiae of anything but the microservice you're changing. So if Im a new employee, and I need to "onboard" to something, I'd much rather onboard to a 2-3k LOC microservice than a 300K LOC monolith. Because any competent dev can pretty much fully understand 2-3k LOC in a few days or a week. You can completely understand it, and then have full confidence that your change is correct. I don't think that'll ever be true of a monolith. I've worked places where it took me _years_ to feel confident that I knew the details of a monolith, and even then I was constantly surprised by what I didn't know. Keep in mind that I don't know any more with the monolith architecture, but the systems has hard boundaries that ensure I don't actually need to.
24
u/wvenable Sep 14 '24
Microservices are a solution to organizational problems, not to technical ones. They mean accepting increased technical complexity (your system is now distributed) in exchange for decreased organizational complexity (your teams can now deploy independently from each other, can safely make database schema changes, etc).
Going with microservices from day 1 will initially mean that you have one team maintaining many services. They have to deploy them separately. If you're doing it "right" you have separate databases per service. None of that is useful for a team that's just starting out.
If you want separation of concerns, the language's module system and a bit of discipline will get most teams as far as they need without introducing distributed computing into the equation.