Yes, a thousand times yes! Microservices are yet another tool in the box but they shouldn't be used on everything. And it makes no frigging sense for a startup or any new project to start with microservices...
The main advantage of microservices are in scaling and in reducing complexity of a big system but those advantages only make sense when you have enough traffic so that you have to scale or when your system has become complex enough to warrant microservices.
When first starting development, the most important thing is speed of development to get feedback from users as soon as possible. It's much faster to develop a clean, well optimized monolith than to spend a lot of time developing a whole bunch of micro services.
And while thinking in term of microservices will help you to better conceptualize your software architecture, at this stage, you don't have all the informations needed to have a clear idea of what the final architecture will be and you'll often end up with microservices that are divided in suboptimal ways causing a lot of pain.
The article didn't even mention a lot of drawbacks :
Changing anything means changing half a dozen programs. Potentially in different languages.
Building any new feature into the program means you get to "walk the dependency tree", making sure no serialized stuff from a new version gets sent to an old version. Good luck with circular dependencies.
Related: deleting a field ... never going to happen. We're talking years of planning. Any field added ... ever ... has to be taken along for the ride for years. Oh and don't even think about deleting the code that interprets and supports the field for the same reason.
Also related: best of luck with the interactions between "oh we're not going to do that after all, sorry about asking you to already push that and update the database" and the "we really need to do this next thing right now" features. And the
Constant serialization overhead. People go overboard with this microservice crap and the result is that 99% of your program's cpu time is used putting objects to json and back (which is very expensive due to constant alloc'ing), and you have 10-100 times the normal memory overhead.
Microservices should be like optimization : build your program without using them and then figure out where they'd make sense.
yes I know, you can sort-of avoid it these days with cap'n proto and flatbuffers
> Building any new feature into the program means you get to "walk the dependency tree"
Same with monoliths, except it is often a worse experience. At least with microservices I know the interface is all I have to worry about. In monoliths of any size inevitably someone has reached into parts of the program they shouldn't have just to get something 'done quickly'. And this is one of the main benefits of microservices - enforcing the interface boundaries.
> Related: deleting a field ... never going to happen. We're talking years of planning. Any field added ... ever ... has to be taken along for the ride for years. Oh and don't even think about deleting the code that interprets and supports the field for the same reason.
That's just poor design and happens just as much in monoliths. The db is the almost always the challenge when removing a field. I could argue that microservices make it easier since the service providing access to that field could remove it from the db and then dummy it out until clients are updated. Also, why wouldn't someone remove the field from all the clients when removing it from the supplier?
With that said, I agree that microservices should be something that happens organically from a monolith. Think about an amoeba that reaches a certain size and only then do parts split off. I also think there is some ambiguity to what constitutes a microservice. I'm sure my idea of proper granularity is different from others.
> At least with microservices I know the interface is all I have to worry about.
You wrap your code inside a reusable library if you want to encapsulate it and expose only a small public interface. You don't start a new service for that.
It doesn't ever work that way in practice for larger applications though... once you have multiple teams with many developers working on something, those library boundaries fade, and tbh sometimes they should just be bypassed in favor of more shallow layers (for a monolith).
Once there are more than a handful of people working on anything no one person understands the details of the whole. Smaller, specialized services can at least act as and enforce those boundaries as upstream comments said.
>"Once there are more than a handful of people working on anything no one person understands the details of the whole. Smaller, specialized services can at least act as and enforce those boundaries as upstream comments said."
Until you have so many services, that you also need someone that understands the details of all the different services interacting.
Really, if you can't control your developers from leaking through separative concerns, then they'll do it in any architecture. Monolithic or microservices-based.
I think you can have separated services by concern without getting too deep in terms of complexity though... I wouldn't use the term "micro" though... I also think if you are only doing mutation, you can combine them, or do libraries in a control service... there are lots of ways to skin the issue...
Digging down through 7 dll projects in one solution, then 11 in another to add a small feature that should take 10 minutes taking 4 days isn't so much fun... same would go for 30+ service projects...
I'm also not big on starting with smaller/micro services either.. or ORM, or DI/IoC for that matter... Build the monolith and break pieces off as needed. I'm fine with that... I was saying it's easier to herd cats when they're not in the same space as eachother.
The other benefit of a microservice is you can understand it. You can have the entire thing in your head. It's easier to maintain. With a monolith, good luck.
This is true for ANY class you release. I'm not even talking about a service API: if you published a class, and it gets used, you should never delete or change fields in it. You might get away with adding fields to it, depending on various factors.
If you serialise / deserialise you are probably coupled to an underlying type. Modify it instead of extending it and you have pain.
If you parse the raw message, or serialise into a hash, or dynamic type then you have one place to make amends (your parser). Taking things further you can version your messages and map them to versions of parsers, as such you'd never violate OCP (or at least simply mitigate).
Granted all of which is additional complexity compared to your stereotypical ball of mud / monolith that'll let you refactor field name changes etc to your hearts content. Obviously ball of mud approach has draw backs too...
I think he was referring to where the article said that one of the advantages of breaking a monolith into any amount of services is that they can store the data in the location and format that suits their task best, and also be written in different languages.
I don't think it matters how you split it - if the team working on one module prefers ruby and the team working on another requires python for any 'serious' work you need programmers who understand both to get the 'big picture' of your codebase now. That one guy who writes all his stuff in PERL can write his plugin that way because it just interacts via API. :O
If you're using a flexible serialization scheme, such as many JSON libraries, you can exclude the field and have a sane default.. you can also handle this at the service boundary for older clients. Personally, I find this type of coercion to be more reliable than explicit case testing, and usually leads to fewer unexpected results.
Martin Fowler wrote a great post "MonolithFirst" [1] just a few months ago. Quoting him:
1. Almost all the successful microservice stories have started with a monolith that got too big and was broken up
2. Almost all the cases where I've heard of a system that was built as a microservice system from scratch, it has ended up in serious trouble.
That's somewhat disingenuous. Historically all software has been "monolith first" and has only adopted an SOA out of need. The microservice mindset is relatively new, and we're not really going to see it mature for another year or few.
"relatively new"? I've seen lots of places use little http endpoints for discrete tasks. Whether the endpoint lives inside a shared container or has its own embedded server is an implementation detail.
If the argument we're going with is “well, microservices-first is relatively new so we won't know for another year or 3 if this is a mature route to take, but everyone's trying it anyway so let's do that", there is NO WAY I can or want to sell microservices-first to stakeholders.
For "webscale" you're right, and if you can run it all on a single cheap server, then no need to worry about it - small servers are so cheap, the cost per month is insignificant relative to, say, ramen cost per month.
But what if you write your app incredibly inefficiently? Perhaps because you develop it quickly; you're not highly skilled (or not even a "developer"); it's difficult to optimise. It's very slow, seconds per request. That's fine for getting started, but you need to scale it far before it gets to "webscale".
You could just upgrade to a better server; but at some point, the costs becomes prohibitive. The key thing about microservices is that they should be cheaper (because vendors can better utilise capacity; and customers only buy what they need, when they need it).
(2). You don't have to architect the whole project for microservices from the get go.
e.g. If there's a single resource-heavy function, factor it out into a microservice. Your main code becomes super cheap to host; the microservice only uses expensive resources as needed: when and if it runs.
===
At the moment, microservices are a pain to set up and manage. But with tools, it will become very easy to factor out a module into a microservice.
That is, assuming that code is already a separate module - microservices aren't magic pixie dust!
The main advantage of microservices are in scaling and in reducing complexity of a big system but those advantages only make sense when you have enough traffic so that you have to scale or when your system has become complex enough to warrant microservices.
When first starting development, the most important thing is speed of development to get feedback from users as soon as possible. It's much faster to develop a clean, well optimized monolith than to spend a lot of time developing a whole bunch of micro services. And while thinking in term of microservices will help you to better conceptualize your software architecture, at this stage, you don't have all the informations needed to have a clear idea of what the final architecture will be and you'll often end up with microservices that are divided in suboptimal ways causing a lot of pain.