Hacker News new | past | comments | ask | show | jobs | submit login

One should probably not even think of microservices if one employs fewer than 100 programmers. In many cases microservices are introduced because of fashion and/or resume driven design not because it actually makes sense. I prefer refactoring a poorly structured monolith to refactoring poorly structured microservices in every case.



The whole problem starts with calling them microservices. Just call it a service oriented architecture please. The whole micro thing is already an indication of the kind of trouble you are getting yourself into. More respect to the monolith please.


Well, a service-oriented architecture is a more general category then microservices and has been around much longer. In many cases it is much more justifiable on technical grounds. Just to give one example. You have an API that is not the most stable thing in the world and when it misbehaves you do not want it to take the whole application down with it. So you put it in a separate service that can easily be restarted. That is a good technical reason for a separation of executables. Problems arise when people introduce these separations for no good reason. Then one gets all of the problems of RPC and none of the benefits. I.e., one is making things more complicated for no good reason.


> and has been around much longer

There's your problem. People understood the tradeoffs, so it needed a rebranding before it could go through another hype cycle.


This is key. Recently I've become a bit obsessed with naming, and not just because naming needs to be consistent and coherent - how you name something in software dictates how you will think about it, what concepts you will relate to it, etc. The name of one component can affect your entire architecture. I'm not sure how to validate it, but I believe that naming choices are almost as important as application architecture because of their effects on your thought process.


I'm going to build a lucrative personal brand / consulting business by hyping mesoservices, neither micro nor macro, just right.


Reality and Fiction mingle together...

"Mesoservices: Architecture for optimal trade-off between engineering and operations efficiency"

https://www.codemotion.com/talks/mesoservices-architecture-f...


Also known as "Goldilocks services". ;)


I couldnt tell if you were serious or joking, or a mix of both. I think in part because I had the same reaction when I heard about microservices. I thought:

"Uh... we had that back in the early 2000s at least, they called it SOA back then."

And yes we learned back then how painful and complex that kind of architecture was to reason about and support, compared to a simple monolith.

Monolith is truly king unless obviously you're at FAANG scales. 99%+ of shops are many orders of magnitude below that scale.


My favourite phrase here is "distributed systems", and that includes any system with discreete components that communicate over a network internally (i.e. consuming a third-party API does not count; obviously there would always be some gray areas).

And yes, a simple SPA is a distributed system, even if the backend is a monolith.


Another phrase I like to use is 'vertically integrated service'. You need to be vertically integrated to scale horizontally. That is the whole point of microservices after all.


A coworker at a previous four person startup was always advocating microservices.

Having to push back on that over and over was frustrating.

We didn’t even have a real devops guy, or a vpc with properly partitioned CIDR blocks to segregate our databases from the public web and we’re going to start adding the complexity of a microservice architecture?

For what! We didn’t even have _users_ yet.

But try to get folk to dogfood our application since we had no actual users besides the founder and it was like pulling teeth.

Totally backwards to me.


To me microservices should not be an architecture.

You can have pieces of functionality in a monolith that make sense to scale independently, and those should not be micro, they should be meaningful pieces of functionality that justify the overhead of spinning them out.

In a way your comment reflects this, a lot of the places that justified microservices were at a scale where their "microservice" was serving more requests than the average company's entire codebase.

It's "big data" with 10 GBs of logs all over again.


I like them for modularity, message queues and asynchronous events. But you are correct, esp. last one.


Things like message queues and asynchronous events are available for your favorite programming language for in-executable use. You can then do things like running them on a thread pool that has the same number of threads as your machine has cores.


So you're not only suggesting monolith, but single instance? In process and non-shared queues only? No load balancing across monoliths?


Not necessarily. That one can have these tools in-application doesn't mean one cannot combine this with some form of RPC as well. Especially whether one needs load balancing or not seem to be a completely orthogonal issue.

On the other hand, why not a monolith and single instance? If one uses a performant language one would be amazed how much can run on a single machine. If one expects growth one should have some plan to scale, sure, but if one does not go for shenanigans like running queues and the like between applications using some form of RCP one might get amazed how much your single monolith can actually do. All this extra networks stuff and so on is not exactly free.


>On the other hand, why not a monolith and single instance?

Single points of failure are bad. I agree its orthogonal, which is why I inquired further about the, imo, odd suggestion.


Running a single instance doesn’t mean not having a backup.


I didn’t read any of that. I read it as more tools in the toolbox.


Without single instance, an in process queue doesn't provide the same kind of functionality that a shared queue does and would probably introduce split brain kind of problems, no?


Right, you’re taking it as a suggestion, as in a positive nudge to single instance monolithism. However, I read it as merely making GP aware of other options that are on the table.


Plenty of languages offer modularity, message queues and asynchronous events within a monolith. They are quite idiomatic in go, rust and elixir


Splitting a system into microservices can help individual teams be better stewards of their part of the system. They can release on their own schedule, they can use their own linting rules, heck even a different language, and they can have better control of incoming code changes. With a monolith any random developer can go and flip some private method to public, import it way across the modules, and presto you are now building a ball of mud. Need an out of cycle release? Hopefully you have CI/CD or now you have to beg the SRE in charge to do it for you.


> Splitting a system into microservices can help individual teams be better stewards of their part of the system.

Team being the keyword here. If you have 3-5 developers per microservice, you're absolutely okay. If you have 3-5 microservices per developer, that's when it gets ugly.


> With a monolith any random developer can go and flip some private method to public, import it way across the modules, and presto you are now building a ball of mud.

If "any developer" can do it, then the problem is not with monoliths, but rather with your pull request reviews process and lack of code ownership. This can even be helped by Github and other platforms with a CODEOWNERS file.

Microservices by themselves doesn't solve this problem. If anyone has commit access to all micro services, then they can make an even bigger mess, the same way.


I haven't had experience with well isolated modules in a monolith so I'm likely not giving monolith enough credit here. It's possible a microservice organization may still have an advantage by having more of this isolation by default, instead of an uphill battle to get things set up properly.


If you are already doing code reviews, it is trivial to setup.

If you’re using microservices + monorepo, you need exactly the same thing, otherwise people will just commit in your service.

If you’re relying on multiple repositories, you can just split things within libraries and have the exact same effect. You can even have separate deployments with this arrangement.

Not to mention it is also an “uphill battle to get things set up properly” with microservices, so there’s really no advantage in using them for enforcing encapsulation.

But most important: a team unable to enforce encapsulation and code ownership is not ready for microservices at all.


Yes, that is the marketing brochure pitch for microservices.

In the real world, poorly designed microservices make the ball of mud problem much, much worse, and whatever pain you had in deployments in a monolith are now magnified ten-fold. I have not been fortunate enough to see well-designed microservices, so I suspect the ball of mud is the default. Can this be rectified through discipline? Probably, but I haven't seen it.

Asynchronous? Doesn't save you, when an upstream service changes event definitions and emits events with unexpected structure, and a downstream service starts failing. Can this be rectified through Async OpenAPI and rigorous contract testing? Probably, but I haven't seen this happen in a way that helps.

I have seen large companies survive perfectly well on a monolithic ball of mud, and small companies get lost in a mud pit of microservices.

My point is not that microservices are bad, they're not, they're just a tool, but they are a tool that is a poor fit for most companies, in my opinion. I can't speak to the few giant companies that need them and use them effectively; there is a good reason the tool exists.


> In the real world, poorly designed microservices make the ball of mud problem much, much worse

I can see that. I am trying to reflect on why I have such negative experience with a monolith and positive with microservices. It's possible that in the monolith setups I had, poor design was easy by default. No linting, no cross-module ownership interlocks, very slow and costly production deploys. Likewise the microservice setups tended to make poor design harder since code is isolated by default both at compile and runtime.

Can you make a monolith with all the good benefits of modularity but without the complications of network RPC etc.? Maybe, but I haven't seen it yet. (Excluding trivial single-team apps; talking about at least 3 teams and 50+ headcount orgs).

> Asynchronous? Doesn't save you, when an upstream service changes event definitions and emits events with unexpected structure, and a downstream service starts failing

Sure, shit happens. Again my experience may be colored, but when costly mistakes happen in monoliths, it tended to take longer to roll back because of how deploys are structured both technically and on an organizational level. I think I would still prefer smaller units in this case.


Given your negative characterisation of the "ball of mud", I'm guessing you haven't actually read the original paper.

> heck even a different language

There's nothing about writing software in different languages that necessitates separating functionality with HTTP calls.


> There's nothing about writing software in different languages that necessitates separating functionality with HTTP calls

I mean it's only computers and the only limit to what we can make them do is our imagination.

In this case though for the sake of argument what options would I have if I, say, needed to let a remote team add some functionality to my, say, Spring backend but they really prefer to write C# and have their own CI/CD system. I'm not sure how I would accomplish this in a monolith.


> I'm not sure how I would accomplish this in a monolith.

With a library.

Depending on what you’re doing (process ran a few times a day?), maybe even spawning a process is enough.

> what options would I have if I, say, needed to let a remote team add some functionality to my, say, Spring backend but they really prefer to write C# and have their own CI/CD system.

That sounds like you need at most two different services, not microservices.


> With a library.

I don't know what that library is right now. Meanwhile I could set up the separate repos/microservices by the end of the day.

> That sounds like you need at most two different services, not microservices

It is unfortunate that the "micro" in "microservice" is often misunderstood to expect that these are very small and granular components. In practice by and large it ends up being separate services with separate repo, code review, ownership, deploy or CI/CD etc. pipelines. It doesn't have to mean they are actually very small. I know people like to joke about npm components and the leftpad thing but in my experience microservices have not turned out like that.


> I don't know what that library is right now

Are you serious? In which language do you program that you don't have to use multiple libraries daily? You just talked about NPM.

In your example, the C# could output DLLs that have functions that can be called by the Java code. This can give the same encapsulation you get with your multiple services example, including separate deployments, different repo, different language, etc.

You could also use different processes. Please tell me you know what an executable is...

> Meanwhile I could set up the separate repos/microservices by the end of the day

That's because someone set it up for you, not because it's faster.

In your hypothetical scenario of "I needed to let a remote team add some functionality to my, say, Spring backend but they really prefer to write C# and have their own CI/CD system" you didn't mention that "…but we already have a fast way of setting up micro services".

> It is unfortunate that the "micro" in "microservice" is often misunderstood*

It's not, you're using the term loosely. "Two services" do not make a micro service architecture.

Sorry to be blunt, but I'm getting the feeling you're not talking out of experience, but rather repeating popular talking points.


> Are you serious? In which language do you program that you don't have to use multiple libraries daily?

I said I don't know which library would let me make C# method calls from a Java Spring runtime, presumably in the same process. Do you? Feel free to share a link.

> That's because someone set it up for you, not because it's faster.

Yes, the whole point was to come up with a concrete example for the sake of argument, and see how we can accomplish it in practice. We're not writing academic papers here, the fact that this functionality is widely available is a good thing.

> It's not, you're using the term loosely

Yes, me and 95% of the industry. Again, it's unfortunate but here we are.


> I said I don't know which library would let me make C# method calls from a Java Spring runtime, presumably in the same process. Do you? Feel free to share a link.

You don't need a library for that, it's is part of the language. Java can call code from native libraries, C# can export native functions. It can also be another process. [1]

> Yes, the whole point was to come up with a concrete example for the sake of argument, and see how we can accomplish it in practice. We're not writing academic papers here, the fact that this functionality is widely available is a good thing.

The problem is that you moved the goalposts. "I need to interoperate with C# code" is very different from "I need to interoperate with C# code and my company uses microservices and that's the only thing I know".

You can't claim something is automatically worse just because you're ignorant about it.

> Yes, me and 95% of the industry. Again, it's unfortunate but here we are.

Nope. There are exactly zero companies claiming to use microservices when they have exact two services. And it's not about size, by the way, it's about different architectural patterns.

[1] https://www.baeldung.com/jni


> You don't need a library for that, it's is part of the language. Java can call code from native libraries, C# can export native functions. It can also be another process.

Having never done this, I believe you. I am still skeptical of how quickly/effectively you could set up a CI/CD system and the module repos to deploy to a monolith. I wonder how the type interop works there (equivalent of OpenAPI-based code generation).

> The problem is that you moved the goalposts. "I need to interoperate with C# code" is very different from "I need to interoperate with C# code and my company uses microservices and that's the only thing I know".

That's maybe a bit unfair. There are a lot of microservice shops, but I haven't heard many who do this Franken-monolith thing. Remember that infamous microservice dependency graph from Uber? I guess Facebook was famous for doing a monolith but I don't know if it was purely PHP or not.

> You can't claim something is automatically worse just because you're ignorant about it.

I can if the metric is availability/familiarity in the industry, but OK.

> Nope. There are exactly zero companies claiming to use microservices when they have exact two services. And it's not about size, by the way, it's about different architectural patterns.

I don't know, my experience is people like to say they use microservices but they just have a service-oriented architecture. Meanwhile I never ran across an organization that does something like npm modules and goes way crazy with granular services. I don't know, maybe they are out there.


> That's maybe a bit unfair. There are a lot of microservice shops, but I haven't heard many who do this Franken-monolith thing. Remember that infamous microservice dependency graph from Uber? I guess Facebook was famous for doing a monolith but I don't know if it was purely PHP or not.

Your original example was that you "needed to let a remote team add some functionality to my, say, Spring backend but they really prefer to write C# and have their own CI/CD system". I am telling you the classical way of solving this problem. You don't get to change the constraints ("I already know how to setup X") after an answer just to say the answer is wrong/worse and expect not to be called out on it...

Also: It's not a Franken-monolith, dude... it's just a library. Have you ever used ImageMagick to resize images from your microservices? Maybe made a request using libcurl? Maybe had to use a SQL driver that was native, maybe Redis? A NPM package with native code? That's exactly the same thing... I literally don't know of a single language that doesn't use those things...

Plus, there is a HUGE difference between what you asked and a Uber/Facebook scenario. You seem to be under the impression that what I'm suggesting is a replacement for real microservices. No, it is simply a solution for the problem you described.

You described a problem and said you don't know how to solve other than with X. I'm giving you Y. I don't understand what's the issue here.

> I can if the metric is availability/familiarity in the industry, but OK.

Sure, but you can't use yourself as a benchmark for the industry if you're that unfamiliar with something that basic.

> I don't know, my experience is people like to say they use microservices but they just have a service-oriented architecture. Meanwhile I never ran across an organization that does something like npm modules and goes way crazy with granular services. I don't know, maybe they are out there.

Again, there is a humongous difference between "we're doing microservices" or even "we have a service oriented architecture" and your "I need two things to interoperate".


> You don't get to change the constraints ("I already know how to setup X") after an answer just to say the answer is wrong/worse and expect not to be called out on it...

I don't see it as being called out, it's a constructive discussion. The purpose of my example is to see how practical it would be for me to set up a monolith-based CI/CD that could support multi-lingual, multi-repo teams. I have a better idea now, maybe have them publish to a local Maven style server, and kick off a monolith build when there is a new library version? The monolith can then bind them together and rebuild. I'm not sure how the host interfaces would get regenerated still.

Good examples re: libcurl, ImageMagick, etc. How would we deal with very frequent changes there? I know that upgrading a SQL driver is not a task we take lightly, and I would love to see how we could make this easy to do on a daily or hourly basis. Mainly we'd need auto-generated strong types somewhere on the interface, again, like OpenAPI but for libraries.

> You seem to be under the impression that what I'm suggesting is a replacement for real microservices.

This discussion started with several suggestions that monoliths could do just as well as most microservice setups, and I wanted to do an exercise to see how practical this would be.

> I don't understand what's the issue here.

There is no issue. Who said there is an issue? So far so good.

> Sure, but you can't use yourself as a benchmark for the industry if you're that unfamiliar with something that basic.

I know and/or interview enough people across the web-dev and game-dev industry that I feel I have a sizable sample of data points to form an opinion that is not purely a guess of a single person.

> Again, there is a humongous difference between "we're doing microservices" or even "we have a service oriented architecture" and your "I need two things to interoperate".

Sure. The two things example was just a distilled example for the purpose of a thought experiment. We can easily extrapolate to an org with tens of services where maybe most people like to use the default environment like Java/Spring but a few teams maybe prefer or their use case calls for something different like Python or C# or whatever. If anything it would be even more difficult to stand up a monolith there with more and more varied components.


Publishing to Maven definitely works.

Updating SQL drivers, etc, is not trivial because you don't have control over the code, but if you have enough integration tests (or at least proper failure handling) for your separate library then you can update with the same frequency as microservices.

I think it's fine to do this thought exercise, but you're massively discounting the difficulties of microservices, while making up obstacles and mocking ("Franken-monolith") every other suggestion. Any company that doesn't already use microservices (and doesn't also have people with experience building infrastructure for them, rather than just using) is gonna have a harder time with a microservice solution than you currently do. It is perfectly fine to extrapolate from your own experience, but you're discount things without any research whatsoever and saying "nobody knows about it" or "nobody uses it" in a very disrespectful way. Another post of this discussion about code ownership is exactly the same: it takes literally seconds to write a simple codeowners file in GitHub, while you make it seem like it would be an Sisyphean task ("an uphill battle") compared with microservices just because you're not aware of it. Some things are not hard, maybe you just didn't heard of them yet.


If you don't even have CI/CD yet I'll argue that your team has not reached the operational sophistication required for microservices yet. There are many ways in which microservices

Also if individual devs can reach out across the codebase and turn private methods public, it is the pull request review procedure that you need to improve, not the architecture.


In process queues don't offer the same capacity smoothing as a shared queue. I don't think most of those queues offer persistence either. They're really not equivalent, are they?


This doesn't match my experience at all. In particular, in the case where a small team is working on a series of small projects it can make a lot of sense to split up the components so that any one of the small projects can be built with one or two existing generalized components along with some custom machinery and some glue code to bring it all together. That way development of all of the small products can contribute to some well honed components that get shared by multiple products and development cycles.

It seems like this is not coming up because the most common context of application is one or more teams working on a single large project probably forced to grow as fast as possible because of the funding structure involved. Increasingly, though, there are companies doing software development without the need for focus and scale that is so common to venture capital powered groups.


The major difference is whether the small projects are independent applications that use some shared libraries (what I think you mean by "existing generalized components") or whether the small projects all talk to each other to create a single large application.

If it's the former then you're just talking about refactoring functionality into a shared library, but at the end of the day you're still just building little monoliths. You don't have to worry about most of the problems that come up with microservices.


It is worth thinking about them before you need them because by the time you gain the skill and infra needed to support them, you’ll have scaled so large that your ability to coordinate and communicate will be overwhelmed.


How many startups out there have run into the problem of "oh no, we got too big too fast"?


A fraction of the ones that are successful.

I suppose what I really mean is: If your leadership subordinates (especially new joiners) are starting to struggle to coordinate, consider the possibility that you might already be at that point yet emotionally attached to the notion of staying small as you double or quadruple in population.


I can guarantee you that most systems out there could serve production traffic on an old laptop, with well-written code and lean database queries. I have done things in MySQL v3 in 2006 that should not be done with a modern database even today (a taxonomy search engine 3 levels deep. Never again).

In the age when database trips and network trips are treated as "free", we somehow arrived at MORE complicated solutions, like microservices.

A "hello, world" problem in 99% of the cases is a "hello, world" problem. At Google - it is not. It's a scale problem. Everything is a scale problem at Google first, and a business logic problem second. The FAANG alumni has convinced the new generation of developers that everything is a scale problem.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: