12 ms·
Make microservices look like monoliths
- mati365 3y agoIt makes no sense. Why not just create modular monolith?
- sirwhinesalot 3y agoMass psychosis.
- intelVISA 3y agoI love a good modulith.
- voidfunc 3y agoBecause all these idiots who pitched microservices super hard need to undo the mess they've created while self promoting themselves into new thought leadership roles.
- switch007 3y agoUffff Spot on. And how do you know you’re not a thought leader? You call yourself one
- claytongulick 3y agoYeah, I was just talking to the CEO of a startup that I built the tech for, and still have a small equity stake in. They formed a partnership with some dev shop that's going to rebuild everything that I made (that's working great and scales well). I asked her why, and she said "because they say that doing microsevices on Azure is better architecture". There goes that bit of equity, I guess. /shrug
- migf 3y agoThat's terrible, so sorry
- 88913527 3y agoIs it the fault of the thought leader, or the loads of juniors asked to implement the architecture but don't really understand it? If everyone had better system design knowledge, it wouldn't be so bad. 90% of the engineers in my organization don't understand the function of an API Gateway, for example. So the thought leader does propose a reasonable solution, but then it doesn't work because the organization doesn't have the hard skills necessary to deliver. I'm sure there's other reasons microservice-based architecture fails, but in my experience, this is a primary reason.
- dasil003 3y agoI feel this comment might go over people's heads if they take the connotation of a "though leader" as someone who makes a mess of things with overcomplicated solutions and then leverages it to greater roles before the consequences of the mess are discovered. However, I've definitely seen this problem even with legitimately strong, seasoned technical leadership, where the vision is great, but the team just doesn't have the skills to pull it off. You can't have good macro-engineering without good micro-engineering. The problem with the cambrian explosion of tech is that it obfuscates the basics that engineers need to understand. Junior engineers end up struggling just to stay on top of incidental complexity and many come to the conlusion that building good software is just about learning enough languages and tooling, when in reality they are barely keeping their head above water and never learn the deeper lessons of what works and doesn't in software systems.
- bch 3y ago> juniors asked to implement the architecture but don't really understand it? Can you reasonably expect a junior engineer to push back here and generally get traction? If this architectural decision has been made, it’s been made. At higher levels. >If everyone had better system design knowledge I don’t think this is a junior devs fault - they’re junior, after all. > but then it doesn’t work because the organization… Bingo.
- jawns 3y agoI can think of a few cases. For instance, say you want to make parts of your codebase open-source and self-contained, but others closed-source. It can be easier to carve off the OSS and treat it as if it were a third-party application. That's not the case here, where the code lives in a monorepo but the services are many.
- dec0dedab0de 3y agoIn that case it would be just as easy to have the OSS app be used directly by the closed source app instead of spinning up another service. It could be a library, a plugin, or even just a separate app that your internal app shells out to. Basically, a separate OSS release really shouldn't be a consideration for deciding to run it as a separate service or not. Though it is an excellent reason for a separate repo.
- 2c2c2c 3y agoOn a large/quickly growing team the risk is folks begin to not respect the modularity and you end up with just a regular monolith Perhaps formalized abstractions around these barriers is a good idea? At the very least better than the 60 kubernetes services at my 100eng headcount team? :-)
- wizofaus 3y agoOne major criticism I have of the way modules work in many stacks is that the dependencies between modules are hard to visualise and/or manage. Certainly in the C#/.NET world it's very easy to accidentally end up with one module depending on another that depends on the initial module via some chain of dependencies. And it's too easy to add extra dependencies to some low-level module that's supposed to be a "core" base layer module that's used across the board. That's less of a problem with microservices, esp. in a multi-repo environment, where you can enforce boundaries more easily. It's one of the few points in favour of microservices, from what I've observed so far - that you can safely make a change to a particular microservice and know a) it's definitely not going to break the CI/CD pipeline for the rest of the product b) if you have introduced a bug, there's typically very limited impact it can have.
- Quekid5 3y agoExactly. On the JVM (at least, dunno if C#/.NET has a similar mechanism) you can technically get away with using OSGi which can load things into separate classloaders along with all implementation-dependencies such that you can truly separate the API of a dependency from its implementation. Alas, support for OSGi in the general ecosystem is abysmal, and the next best thing seems to be microservices. Honestly, I find it pretty shocking that so many mainstream languages don't support this sort of "local isolation" better. The diamond dependency problem well-known at this point. (To be clear, in our shop we generally only do this for very problematic dependencies that have a tendency to break backward bincompat on a whim. Those are almost always the most painful ones, especially if they are in turn dependended on by many of your project's other dependencies.)
- 3y ago
- Toine 3y agoMost devs, even senior, have no clear idea what a modular monolith is, let alone implementing one
- regularfry 3y agoThis is a way to modularise a monolith. It just happens to also be a way to allow it to build out to a distributed deployment. I hesitate to say "microservices" because I strongly suspect that the 95th-percentile use case will see all the parts strongly coupled and deployed as a single commonly-versioned blob. Not saying that's a bad thing necessarily, but if one of the benefits of microservices is loose coupling, it's not going to encourage a good microservice architecture.
- Zetice 3y agoI’d rather compose my systems with widely understood and commonly used components that make hiring and maintaining over time more of a puzzle problem than a, “learn a new framework” problem. This feels like we make our jobs harder than they have to be, sometimes…
- vineyardmike 3y agoI’m working a short term job (while they find a FTE hire) for a friends startup since their last SDE quit unexpectedly. The last employee tried every framework and architecture pattern under the sun. This company has more micro services than employees and customers combined. Each one is like ~200LOC, uses a different framework, etc. I’ve spent the last month just deleting shit and simplifying shit. You don’t need a caching layer for customer data when your entire SQL database is 100 rows in a single table. You don’t need service discovery when everything runs on one node. My point is that this entire system was designed around their last engineer’s bookmarks of interesting things, not designed to be maintainable or easy to iterate upon.
- anotherhue 3y agoBlame a few things: 1. The developer, of course. 2. The person who let them do it. 3. The eight thousand devtool companies that pitch their solutions to developers. 4. The hiring managers for whom 'resume driven development' is effective. 5. The VCs who wrote the playbook for how all these companies (and the dev tool companies) have to grow. 6. The Fed for so much ZIRP that VCs are in power. 7. The government for uncontrolled spending that needs low interest rates to sustain. 8. The electorate for electing the government. 9. The media for influencing the electorate. 10. The human brain for being susceptible to influence.
- nologic01 3y ago11. The developer for having a human brain (well some do)
- theshrike79 3y agoIt might've also been CV Based Programming. You just pick the crap that looks good on your CV and use that. Repeat until you get a new job.
- empthought 3y agoThe Eight Fallacies of Distributed Computing: https://nighthacks.com/jag/res/Fallacies.html https://nighthacks.com/jag/res/Fallacies.html
- hn_throwaway_7 3y ago[flagged]
- civilitty 3y agoHow about just stop making microservices and go back to monoliths? Then you don’t have to shoehorn two things at the same time!
- mabbo 3y agoI spent a decade at Amazon (SOA all the things!) and then a year and a half at Shopify (single Rails monolith for all the things!). I think both strategies have pros and cons. But critically, you need a company culture that supports whichever choice you've made. If you have a company where each team gets to totally decide how they want to implement their stuff, sharing a monolith between teams can create a mess. Ownership issues to be resolved, code quality/style issues, operational issues. Monoliths require alignment.
- ranting-moth 3y ago> Monoliths require alignment. So do microservices.
- spicybright 3y agoI think GP's point on company culture is the right answer. My only thoughts to add is monoliths can be aligned as well as microservices, if not a bit easier depending on the team. You have to align microservices to talk to each other anyways, and there's no reason you can't make those boundaries work in one codebase instead of many. That said ownership is more important in a monolith, whether that be a single team of architects or architects responsible for a specific well defined part of the code base. Having a solid process for only allowing well thought out code in is a cornerstone to keeping alignment.
- zerbinxx 3y agoThe worst thing is the many-monoliths/mini-monoliths problem that you get when each team thinks it has ultra special needs and absolutely must build everything from scratch, even if it’s a near duplicate of something someone else built 2 months ago.
- jerrygenser 3y agoI wonder what the rationale behind AGPL is? Prevents it from being used for commercial SaaS
- pjc50 3y agoThat is usually the rationale behind such licenses, yes.
- ars 3y agoMy issue with microservices isn't the network calls, it's the extra work to keep the source code up to date. New spring library? Have fun applying the same changes to 14 different microservices. Microservices might make sense with completely different teams developing them - but multiple microservices in the same team, with the services talking to each other, really doesn't make sense.
- hinkley 3y agoChange to build process? That's 20 build plans you have to update. Yeah, it's just a laugh a minute.
- mjr00 3y ago> New spring library? Have fun applying the same changes to 14 different microservices. On the flip side, at some point monoliths can get large enough that upgrading libraries or runtimes becomes an incredibly difficult problem. When I was at Amazon a major service was finally getting upgraded from Java 7 to Java 8. Took a cross-functional team 6 months (!) to make it happen due to the massive amounts of existing code. And these are AWS engineers who are much technically stronger than average. I don't condone the 500 LOC style of true microservices, but people tend to go back to the extreme of "just make everything run in the same process with the same runtime and same dependency chain" as if that doesn't come with its own set of headaches. (also for what it's worth -- in correctly done SOA, you don't need to upgrade libraries in lockstep. So that Spring upgrade can be done on a per-service basis as needed.)
- letitbeirie 3y ago> at some point monoliths can get large enough that upgrading libraries or runtimes becomes an incredibly difficult problem Some languages (e.g. Go) make this easier than others by allowing two versions of the same import to coexist, but this is why we broke up our Django monolith a few jobs ago.
- mjr00 3y agoYeah, the library problem has some (ugly) solutions in some languages, like Go allowing multiple versions as you mention, or doing JAR shading in Java. But I don't think there's a (mainstream) language that solves the problem of partially upgrading the underlying runtime. If you've got a Java monolith, it either all runs on Java 7 or Java 8, can't really do in-between.
- vanjajaja1 3y agoI think this is directionally correct. Services should just be standard language classes, and whether that service is hosted inside process 1 host 1 or process 7 host 5 is up to the autoscaling component. The industry is verrryy slowly getting there.
- friendly_chap 3y agoHi! OP here. Yeah in part my motivation for open sourcing this was the fact I kept reading on HN how microservices should be an implementation detail etc. in the past 6 months. I totally agree with that sentiment, hence Actio. For the direction I can take some responsibility but not for the details (yet) ;).
- Justsignedup 3y agoReminds me a lot of erlang and the core features of where the function runs is unimportant. This is solving microservices via dependency injection. I'm not against it, but honestly if you not gonna be thoughtful about it.. Why not just monolith it? Monoliths are only a problem at large scale, and at that scale you have the manpower to create a reliable messaging service for inter service communications.
- zerbinxx 3y agoI think the point here that is getting lost here (not on you necessarily) is that if you write your service clean/SOLID, it really doesn’t matter if/when/how you make that decision to cleave it off into its own service. Monoliths are only a problem with scale, but there is absolutely no guarantee that your engineering team will scale at the same rate as your userbase. You know the story: tech product strikes gold, gets mentioned in NYT and becomes a new hot thing and doesn’t even have time to react before they hit scaling problems. It’s not great to prematurely optimize, but if you’re not preparing for eventual success (which requires scaling) is another term for shooting yourself in the foot. Unfortunately, even if you are “scaled up” in terms of workers, monoliths can be really nasty/resistant to many hands making the work lighter because they of how tightly coupled things end up being. Why not monolith it? Maybe one part of the app evolves to really need a time series database or it really does some crazy stuff with image editing or it has new special dependencies that take an eternity to build, and you don’t want to add 20m of build time every time you mess with the rest of the codebase, none of which needs/expects the time-series/image-editor/complicated build thing to be there deployed alongside it. That’s like OG logic of why you want microservices, and it still makes a lot of sense, just people get carried away with cargo-culting on their thousand-microservice hellscapes where each API has four routes and 4000 lines of deploy config, boilerplate, copypasta.
- patrick451 3y agoMicroservices don't solve the tight coupling problem. Rather, they make dealing with it even more painful because rather than updating assumptions across modules, you update them across different units of deployment. This leads to ossification because it is even more difficult to fix bad architecture.
- ivix 3y agoI find a lot of people conflate both service separation for human factors and service separation for technical factors. Unless you have multiple independent development teams you do not need to worry about the human factors. Addressing them fully is always going to come at a technical cost in terms of things like latency and complexity. Separation for technical reasons (generally scaling) may well be a factor but easily addressed without building 'true' microservices, for example with serverless functions. Don't let the purists sneer at your architecture because it's not true microservices.
- Lapsa 3y agono, thanks
- anilakar 3y agoMonolithic microservices look like a perfect anti-pattern. Worst of the both worlds, so to say.
- friendly_chap 3y agoNot much is monolithic about this tbh. It's just trying to hide the architecture implementation detail (monolith vs microservices) instead of exposing it like most existing frameworks. IMHO the monolithic microservice (or distributed monolith) is when you don't have firm service boundaries - eg. services can read each other data if they want, sidestepping endpoints/handlers. Actio avoids that mistake. Each service has its own database.
- azangru 3y agoThere are a couple of relevant recent talks on the subject: - Top 5 techniques for building the worst microservice system ever - William Brander - NDC London 2023 (https://www.youtube.com/watch?v=88_LUw1Wwe4 https://www.youtube.com/watch?v=88_LUw1Wwe4) - Don’t Build a Distributed Monolith - Jonathan Tower - NDC London 2023 (https://www.youtube.com/watch?v=p2GlRToY5HI https://www.youtube.com/watch?v=p2GlRToY5HI)
- ketzu 3y agoIt is such a weird feeling to come across a topic I haven't read on in a while, watch two videos on it out of random curiosity, hop on hackernews the next day, and get a recommendation for the exact same videos. I very much enjoyed the 5 techniques and many of the tidbits. I also liked "Avoiding Microservice Megadisasters" but mostly for the entertainment value (https://www.youtube.com/watch?v=gfh-VCTwMw8 https://www.youtube.com/watch?v=gfh-VCTwMw8)
- iamkoch 3y ago[dead]
- haspok 3y agoSo you are trying to build Erlang without Erlang and OTP. Nice try :) You are maybe 5% there. How about the rest? Error handling, handling network issues, latency, partitions, deployments, scaling etc... I would also argue that because of the async calls (NodeJS is single-threaded, right?) you can easily run into weird and unexpected issues where two sequential service calls return out of order (which is impossible if they are just method calls, but very likely if they are sent over the network). How do you handle these cases? Do you just block on each call over the network and hope for the best?
- Cthulhu_ 3y agoThat was my thought too, this has been done many times before; I'd like projects like this to show their homework and prove they've tried e.g. erlang, scala, etc for the same thing, the pros and cons, the dealbreakers (and there won't be many dealbreakers), and why building a new tool is worth the effort.
- pibi 3y agoMy goto for this kind of task is moleculer: https://moleculer.services/ https://moleculer.services/ Fast, battle tested, vue2-like approach, great documentation, good community. The automatic indipendent-scalability as an option is usually the main selling point of these solutions, but honestly I think the real pro is the "composition" approach, which is essential if you want to keep a clean and well-organized codebase. On this regard, I found moleculer pretty great even for large teams.
- RamblingCTO 3y agoWhy on earth would you use javascript for that? There are way better alternatives out there like Go, Erlang, Kotlin, or any other of the typical backend languages. Is it too much to ask for frontend devs to learn a new language?
- migf 3y agoWorks great for applications where you spend most of the time waiting for a database. The dynamic type system makes it easier to write testable code with less abstraction overhead. Faster to train up junior devs. That said, you * must * set up the codebase with appropriate guard rails or bad things can happen.
- RamblingCTO 3y ago> Works great for applications where you spend most of the time waiting for a database. You mean callback hell? :P > The dynamic type system makes it easier to write testable code with less abstraction overhead. My biggest issue with js/ts is that there's nothing really enforcing good code, unless you decide to adhere to it. Also: npm is utter garbage. > Faster to train up junior devs. I think go is better in that regard, less random happenings. But yeah, in general I get what you mean!