14 ms·
In Defence of Monoliths
- thecourier 11y agoI have seem cases when a group of stateless monoliths would have solved more efficiently a business case than the micro-services alternative. I'm not saying micro-services are a fad, because they are great for isolating domains and degradation of service, but that comes with a high amount of boilerplate code for remote invocation and serialization. I would personally say, if your project has not reached 10,000 lines of code do not go that way. also if you can solve the problem at hand with a cluster of stateless monoliths, keep it simple. Dear friends, keep at hand the Occam's razor
- 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.
- 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.
- Glyptodon 11y agoOne thing I don't think gets hammered on enough is that if your organization is not large microservices will create a lot of overhead for little gain. If you have few developers most of the time it's a lot more efficient to have a modular monolith than it is to have 50 entirely different rocks. Decentralizing teams, decision making, and allowing increased independence of agency within a larger org is great. Trying to do the same thing when you only have 5 people is usually borderline crazy.
- patrickmay 11y agoOne advantage of a microservice architecture not mentioned in the article is the ability to scale services independently of other services. Being able to fire up more instances to address a bottleneck is often much simpler than managing threads in a monolith.
- bozho 11y agothat is true in some very rare cases. CPU-intensive bits of the application should definitely be separated, so that they can scale independently. But that's not the main point of microservices.
- acdha 11y agoI don't think I've ever seen a piece selling the benefits of microservices which didn't mention the scaling or reliability benefits as a primary motivation.
- abritishguy 11y agoI would concede that it only happens at scale but I would contest that it is rare.
- deleted 11y ago[deleted]
- beberlei 11y agoyou can often as easily deploy a monolith to multiple servers and grant different subtasks different cpu and memory for their work. for me its just a matter of adjust with the supervisord config for each server, how many of which workers start and run on that machine.
- ap22213 11y agoThis is an important point. If you have a system that processes billions of inputs a day along a fairly complex pipeline, you're constantly scaling up and down. It would suck pretty bad if you had to scale mostly vertically.
- timothycrosley 11y agoIt depends how you do micro services. There are middle grounds. One big gain of micro-services is that it guarantees things are separate and can be handled by separate teams if the need arises. That doesn't mean you need to start out that way. For instance in Python I use hug to create my microservices https://github.com/timothycrosley/hug https://github.com/timothycrosley/hug, then I can just install them to create a "monolithic" services that consumes all the microservices, the great thing is that hug allows you to expose both as a webservices, and as a Python library so I can consume as a Python library with no overhead, until the need to split is evident, and then can split up the services with very little work. Of course the need may never arrive, but the modularity that is forced when using micro-services pays dividends quickly regardless
- untothebreach 11y agoHuh, I had never seen `hug`, thanks for mentioning it!
- eropple 11y agoThis is more or less what I'm doing right now with Dropwizard. I started building this app as a set of separated microservices, but was finding it to slow me down more than I wanted it to--so I flipped it upside-down and loaded every "application" into a single Dropwizard service. Which is uncomfortably like application servers, but I'm using this almost exclusively to get around doing the inter-service wire-up that I'd have to do manually, rather than letting my DI container do it. Each module's still separated, and if we need to fork services off in the future, it's about twelve lines of code.
- _pdp_ 11y ago🅰s always, there is room for both styles of programming. Some applications simply do not require this type of architecture. Testing a monolith is certainly easier than testing thousands of microservices. Debugging is also a lot easier. Dependency management is also hell of a lot easier. Yes microservices (or simply services) are very good at large scale applications but they are simply an overkill for any startup project. Why not concentrate your efforts on selling your product first vs building the perfect infrastructure that no one uses? When time comes to upgrade - well upgrade. Amazon is a good example of a large company making the move from monoliths to services and they executed well. You can also do the same thing when it is absolutely required. You know, refactoring!
- unoti 11y agoThere's a dangerous, contagious illness that developers of every generation get that causes them to worry about architecture and getting "street cred" even more than they worry about solving business problems. I've fallen victim to this myself, because street cred is important to me. But it's a trap. An important meta-idea that encapsulates all of this is remember to solve your business problems as your first priority, and implement technology in service to that goal first and foremost. It's far too easy to put various technology decisions in the driver seat, ahead of the business problems. This leads to all kinds of anti-patterns over the years. For example, I saw software development organizations destroy themselves trying to do 100% pure UML-first software using Oracle's Designer/2000 and Developer/2000 tools, because that was just the "right" way to do things. I've seen organizations destroy themselves in the morass of trying to do things with Enterprise Java Beans (EJB) because it was just the right way to do things. I've seen companies spend 10x more time getting their automated build processes and super duper full test coverage going than they spend trying to actually write software. And I've seen companies navel-gaze over their processes and methodologies and buzzword compliance far more than they worry about meeting the needs of their customers. If you've ever worked for a company with a 15 year history of ironclad determination to use all of Microsoft's latest preferred data access methodologies, then you have first-hand knowledge of another example of this. I'm not saying microservice architecture is a worthless fad, but I am saying that putting your business needs into the done-basket absolutely must be the first priority; never lose sight of it. I'm all for being wary of technical debt, but "technical debt" isn't nearly as dangerous as whatever you call that contagious illness that infects developers and makes them put architecture before business needs.
- pjmlp 11y agoIt would help a lot if those developers spend some time in companies that don't produce software as their main business. Where software is seen as a cost center and is actually developed 100% by contractors that fine-tune existing code bases across multiple years. I guess there isn't better cure to those that tend to follow each fad that pops up.
- Consultant32452 11y ago
- DanielBMarkham 11y agoBeing a new "convert" to microservices, and coming from a classic OOA/D/P background, I read these critiques with great interest. I keep waiting for one that shows me what I'm missing. What I'm finding, however, is that many of these authors have such a broad understanding of microservices are that they miss any benefit. Then, of course, they complain about there not being any benefit, natch. I suspect -- and what I have feared -- is that the term "microservices" has been co-opted and rebranded by a variety of vendors and proponents. The goal here is to sell products and services, not necessarily solve problems. There is certainly a huge wheel of hype in the technology world, where things become cool, then old hat, then abused, then nobody does them anymore, then they return under a new buzzword. Having said that, in the future I'm going to always make a point of defining exactly what I mean instead of just using the term "microservice". My current definition is something like this: - Pure FP - Unix Philosophy - Each microservice has less than 150LOC - Common code, types, and persistence functions are moved to shared libraries to reduce interop concerns Not sure if this makes a difference in the discussion, but I know that it will help me keep straight whether various authors actually have quibbles with microservices -- or are just re-applying their pre-existing OO thinking to a place where it doesn't necessarily map so well.
- Thaxll 11y ago"- Each microservice has less than 150LOC" Sounds like a nightmare, you know how much instances / vms you need if you spawn one thing for 150LOC?
- DanielBMarkham 11y agoNobody said anything about 1 VM per microservice. You're using the term "service" in a way I did not intend (and which is a carryover from other kinds of services) This is illustrative of the point I was making. One of the big benefits of microservices is the total decoupling of the code from the underlying hardware. Things are glued together by Ops, not by code. So you might have all the microservices in one VM -- or spread copies of one critical microservice across a thousand vms. It's all configurable.
- rcconf 11y agoWe've had a lot of issues with micro services. They're extremely difficult to debug and end up being too generic. I argue the reasons why we introduced microservices has merit (massive code base) but does not mean they are simple to use/maintain. Here are some examples: 1. A chat service (race conditions, synchronization issues between the game server and chat service that had to be debugged using sequence diagrams) 2. A payment service that handled Facebook, PayPal, and other payment methods. (race conditions, complicated integration, difficulty upgrading for different products, complicated code base to handle multiple use cases) 3. An authentication service (complicated protocol, hard to integrate) 4. A worker service for handling bcrypt (because blocking a single threaded server for 0.5 seconds is not acceptable, race conditions) 5. A tracking service (could have probably just been a library you included instead of hitting an API) Core issues: - Race conditions - Synchronization issues - Complicated to upgrade/maintain for multiple products - Become too generic and solve multiple problems (services tend to be used for multiple products in the company) - Extremely difficult to debug - Complicated error handling for when a service is not reachable pro-tip: don't share databases between multiple products for each service, deploy a new service for every product with its own database. I think I'm scratching the surface here, but I would be really careful with introducing this kind of architecture when you can do it all in one server.
- debacle 11y agoI don't mind to sound crass, but it sounds like you implemented microservices poorly. You could s/microservices/threads/g on your post above and it would point much more to a problem with your implementation rather than a problem with threads.
- exelius 11y agoYeah, my general rule is that unless your production environment is already so complex that you have multiple people who do strictly DevOps work, you should probably stick to a monolith. It's a lot easier to transfer state between multiple deployments of the same monolith than it is to go full microservices. Microservices are a gigantic pain in the ass. They increase operational complexity significantly, and they will require you to make a lot of investments in building/buying/implementing infrastructure around things like logging, monitoring and config management. Your number of possible variables in QA explodes exponentially, and suddenly you have to worry about things like API versioning. If all of this sounds easier than dealing with the tech / organizational debt in your monolith, then microservices may be right for you. Otherwise, save yourself the trouble and focus on scaling your business instead of your technology platform.
- Sleaker 11y agoI'm not advocating for microservices, but I think the blog post fails to understand the difference between patching a single microservice and deploying a single microservice without needing to restart your entire environment stack, and patching a single module in a monolith which requires you to restart the entire monolith... Maybe that's not an actual issue but the author seems to disregard the fact that restarting a single microservice is explicitly different than restarting the entire monolith for the very reason that time may become an actual factor.
- marcosdumay 11y agoYou know, nearly all software running out there does not need to be online 24x7. And for the tiny exception that needs, reducing restart time is just not the way to get that 99.9% uptime.
- lemmsjid 11y agoNot disagreeing with you, just adding some color. We have a monolithic application (well, an application composed of many libraries that have a dependency tree, but live in the same process) that contains individually deployable services that talk to one another over RPC. So when you're patching part of the codebase, you can deploy a branch to the servers that are executing the code you've just changed, thus no need to restart the whole thing. But you still have the benefits of shared libraries, moving functionality between services, collapsing service calls that are no longer performant, adding new calls temporarily, etc. In this model, you can introduce and remove service calls when it's useful, as opposed to as a result of how the code was put together. You will often do this for performance reasons, but just as often you'll do it for deployment flexibility. When you want to prototype something new, you can create a new service, branch the codebase, and have it talk to the rest of the infrastructure via service calls. When you're done you can keep it as a service, or, just as often, you can collapse the service back into other services so we don't have excessive RPC calls. When would we consider moving to services backed by different codebases? If our company were to grow so large that highly disparate teams would want to manage their own dependency trees--that's around when it makes sense to me to go microservice. (I not sure I'd call it microservices then, more SOA).
- debacle 11y agoAn honest question - has Martin Fowler ever written any code that makes him so much of an authority on software design? I don't disagree with everything he's said, but what contributions has he made that makes him so much of an authority on how I write code?
- jjbiotech 11y agoThat's an impressive logical jump you've made there. Starting with a man simply writing a blog post with his opinion on software architecture, all the way to implying that he's an authority on writing code. He never said he was an authority...
- debacle 11y agoMartin Fowler (not the author) definitely thinks he's an authority. Have you ever heard him speak?
- cableshaft 11y agoYou Google "Martin Fowler" and the snippet of text that accompanies his personal website is "Object-oriented programming expert and consultant, one of the leaders in refactoring, author of the book 'Refactoring: Improving the Design of Existing Code'" He's a self-proclaimed "expert" and a "leader". Yes, he's basically saying right there that he is an authority on writing code. That being said, I've read some of his Refactoring book awhile ago, and it's mostly good advice from what I remember.
- abritishguy 11y agoI work for a startup bank in the UK (Mondo). Our Go microservices architecture allows us to maintain velocity whilst staying secure. The core banking services that actually move money around are isolated from the more "fluffy" customer facing ones that we want to be able to push updates to several times a day. We have to have incredibly rigorous procedures for updating services that control money, if we had a monolithic architecture then these procedures would have to be used even if the change was simply cosmetic.
- csears 11y agoI think the choice of monolith vs microservice should be largely driven by the size of your team. Some guidance I heard on a podcast recently (can't recall which) was to only consider microservices if you had more than 50 people trying to deploy code in the same app/system.
- bullen 11y agoThe important thing is to improve tools, and with a monolith you can't do that. So build a distributed PaaS with hot-deploy, then a distributed HTTP database; then you can use microservices without any of the problems mentioned (complexity becomes a non problem since everything is using the same complexity and it very quickly becomes bug free, overhead is removed by PaaS)! The important step with microSOA is that each developer can choose his tools. That trumps everything else.