8 ms·
> decentralize all things – well, the services are still logically coupled, no matter how you split them. I think this is missing the point. It isn't just abou
by cpitman 11y ago
> decentralize all things – well, the services are still logically coupled, no matter how you split them.
I think this is missing the point. It isn't just about decentralizing services, it is also about allowing you to decentralize teams and decision making. With very large teams working on a single monolith, features that are complete often cannot be deployed because of the larger organizational overhead of planning and coordinating a release. The higher coupling in most monoliths also restricts a teams ability to try new things and take risks.
If performance of technology is the only metric that matters to you, then yes, microservices are probably a horrible idea. If you are having difficulty scaling your teams, then it might be worth looking at.
- vonmoltke 11y agoI don't see how microservices makes that overhead go away. That overhead is really a matter of proper systems engineering. With well-defined interfaces and properly-sectioned functional components teams can work just as independently on a monolithic application as they can on a microservice application. Similarly, a poorly-sectioned application with bad or nebulous interfaces will be a planning and coordination nightmare regardless of the architecture. What I think the microservice architecture does is force some measure of good systems engineering on a team. You can't design a microservice application without putting effort into deciding how to divide the functionality and defining how those functional blocks will work with each other. You can get away with not doing that (until it's too late) when designing a monolithic application.
- optimuspaul 11y agoI've actually found overhead to increase significantly when using micro-services vs a monolithic codebase. Automated integration testing is far more complex. Ensuring that a change in one micro service doesn't break things in another can be daunting. But when you have a common codebase dependencies are far more clear. Of course if you have tons of cash and resources to throw at it then that isolation could be beneficial. But is it worth it? I have no idea.
- vonmoltke 11y ago> Ensuring that a change in one micro service doesn't break things in another can be daunting. That is what I was referring to when I mentioned nebulous APIs. In a properly-designed system, each component (be it a module of a monolithic system or service in a microservice system) should be a black box with known APIs and no side effects. Part of defining the API is defining the acceptable values that can come across the wire. If designed correctly, breaking another service should not be possible without an API change. An API change should be something signed off by systems engineering and communicated to all affected teams before it happens. Done right, this is a fairly heavyweight process and so, as others have said, is only something that should be done when a project reaches a certain level of complexity (both code and team).
- wvenable 11y agoThe more your system is broken down into smaller components the more you have to break an API to make a change. Unless all change consists of nothing but bug fixes and performance enhancements, changes to the API is as common as anything else. If your need is respond quickly to changing requirements this setup falls flat.
- cpitman 11y agoYes, if services are too small than it will be hell. A lot of microservice proponents talk about how services should align to a "bounded context", essentially a domain of the business. That makes it more likely that (1) there are well defined interfaces between business domains and (2) changes will be grouped into a single service as opposed to requiring changes throughout the codebase. Also, if it's being done right, you rarely "break" an API in a single blow. You add new functionality, possibly via a new API. You give your consumers ample time to migrate. Only then do you remove the old API. One of my old teams had a hard requirement that all APIs had to be backwards compatible for 2 versions, which was essentially a year. We got very good at adding functionality without any impact on consumers that had not upgraded yet.
- lowbloodsugar 11y ago
- tkahnoski 11y agoCaveat: I have not implemented microservices, but have plenty of experience with monoliths. "With well-defined interfaces and properly-sectioned functional components teams can work just as independently on a monolithic application as they can on a microservice application" Basically if you build a monolith such that it is not a monolith things are ok. This doesn't happen in my experience. Speaking first hand, working with 40 engineers on a 500k+ line codebase. The monolith is as robust as it's weakest component. There are secondary organizational effects that come into play as well with monolith architecture that need to be mitigated. Because there's a single monolithic platform, the org believes it can throw any set of engineers at a problem in the monolith and get the same result. This largely gets down to what philosophies you buy into, but I personally believe long lived teams with long lived missions are better capable to innovate (team builds depth of expertise in a capability vs breadth). There are plenty of ways to do anything wrong of course. More so, as the team scales to more engineers, the monolithic architecture re-enforces the monolithic engineering org which means an increase in communication overhead. My experience is that by creating a monolith you create one way to do things that leaves the organization less adaptable to change to implementing a new technology or pattern.
- pdpi 11y ago> The higher coupling in most monoliths also restricts a teams ability to try new things and take risks. I think it's you who's missing the point. That right there is why. Turning your monolith into a micro-service architecture should add up to basically: - Wrap your internal modules in your favourite form of RPC - Replace the modules with stubs that call the RPC If you need more work than that, the problem with your application isn't being a monolith, it's having functionality be way too tightly coupled. If turning your application into a micro-service architecture actually _is_ that simple, then you already have well-delineated modules that your teams can focus on. Deployment is just about integrating the latest stable version of each module, and the decision process within each team needs only respect the contract around the interface they provide -- same as a micro-service. Saying you need a micro-service architecture to keep a sane internal structure to your application is a symptom that you need to review your engineering practices, because people aren't respecting the interfaces, and it's throwing out the baby with the bathwater.
- to3m 11y agoDon't forget that an RPC call can take longer to complete than a function call. Loose coupling doesn't imply that your program expects operations to routinely take 1ms to return results.
- mje__ 11y agoOr sometimes 10s, or never, or partial results, or dropped connections, or... The network is not reliable.
- pdpi 11y agoI was replying to a comment that ended with "If performance of technology is the only metric that matters to you, then yes, microservices are probably a horrible idea". I figured that it'd be more effective to make my point without bringing performance into the discussion.
- cpitman 11y agoI get what you're saying, and I've tried both ways: using project structure to explicitly force modularity vs trying to instill culture and practices to preserve modularity within a monolith. I should mention I am a consultant, so I tend to work in enterprise environments with varying levels of practices and maturity. My experience has been that lots of different people will touch a codebase over the lifetime of a piece of software, and they will have varying skill levels. Even if everyone on the team right now will avoid creating a ball of spaghetti, at some point everyone involved will be gone. Patches and new functionality end up getting bolted on and added to an ever growing list of technical debt (we'll get to it, we swear). 10 years down the line no one can maintain it because no one knows what the interactions are across the system. Splitting code into separate services/codebases doesn't totally prevent this from happening, but it does make it a lot harder. First, adding coupling is no longer the path of least resistance when you "need to delivery yesterday". Second, each service is significantly easier to grok than a single legacy monolith, and therefore easier to refactor back to sanity. Vaguely related, I also really like how microservices offer a non-insane approach to modernizing a large system. A lot of my clients have large highly-coupled mainframe applications written in Smalltalk/COBOL/etc. They want to migrate to a "modern" language (ie one with a workforce). Big bang migrations almost never work, so we end up carving off functionality, re-implementing it in the new framework, and then integrating it with the monolith via messaging/services. Microservices make it easier to pull out one piece and rewrite it, without having to also touch every client.