Separation of responsibilities? Easier to analyze because you only have so many inputs and outputs to a simpler system?
Debugging something that touches a lot of paths in a monolith can be quite nightmarish as well.
I guess what it means is that even if you can build a well modularized system, it will only stay well modularized if you use a network call to enforce it. Well, at least for most companies.
Conceptually, there's nothing keeping you from designing your codebase to work as both microservices or direct calls. I've certainly done it before - each service defined a Java interface, and codegen could hook that up as either a direct call or to route over some kind of layer.
Doesn't a function only have so many inputs and outputs too? Scope capturing/global variables aside.
Sure, and a microservices architecture to me implies a larger movement towards function-esque, idemopotency, analyzability and away from global state.
To me, monolithic architecture implies global shared state that is difficult to reason about.
You're mistaken. The operating system largely prevents cross-process memory access. Of course, CPU vulnerabilities can circumvent these protections, but even then your micro services can run on distinct machines while monoliths can't.
> The only way this would be helpful is if your whole goal is to make something (breaking the contract) as hard to do as possible
Yeah, that's the idea. "defense in depth".
> And in that case, I really have to ask, who are your teammates that you trust them so little as to literally enforce separation this way? No healthy organization should have to resort to this kind of civil war.
(1) not all attackers are internal
(2) some attackers are internal and many very profitable organizations do restrict employee access to secrets (and in many cases this is required by compliance).
As do programming languages. Yes, a few languages like C allow you to do anything that's physically possible, but most popular languages including Python and JavaScript make leaking function-internal memory to the outside world either very inconvenient or impossible.
As for memory being shared among processes, it's not only not impossible but quite common in performance-sensitive applications. https://man7.org/linux/man-pages/man7/shm_overview.7.html
> many very profitable organizations do restrict employee access to secrets
For one, code is not secret. Secondly, when was this discussion scoped to profitable organizations? A very, very large chunk of HN readers work in startups.
> in many cases this is required by compliance
This argument weakens the entire stance, because it shifts the goalpost from "this thing is good" to "this thing is legally required." Let's stay focused. There are so many implicit assumptions you're taking as granted, I'm starting to doubt this is even an argument in good faith.
I share your doubts that this is a good faith argument, in particular, you keep responding to arguments that I patently didn't make:
> For one, code is not secret.
I didn't claim code was secret, I claimed that we should secure secrets and prevent attackers from executing routines that they shouldn't have permissions to execute.
> Secondly, when was this discussion scoped to profitable organizations?
I didn't scope the conversation to profitable organizations, I mentioned that profitable organizations often secure their applications. I'm giving you an example and you bizarrely think I'm limiting the conversation only to that example. You do the same thing here as well (and suggest that I'm the one who isn't focused):
> This argument weakens the entire stance, because it shifts the goalpost from "this thing is good" to "this thing is legally required."
Again, I give "in some cases security is even required" and you take it as "we're no longer talking about other reasons for which security is beneficial".
Honestly, the "monolith vs microservice" question is interesting, but it's not interesting to debate someone who is bent on responding to arguments I clearly didn't make. :) Whether you're being obtuse on purpose or by accident, this conversation has become dull, and I'm ducking out of it.
While this is obviously a noble goal, you mentioned restricting employee access to secrets in relation to restricting (employee) access to code as well. To me, this is throwing the baby out with the bathwater. We can obviously make things harder for attackers by making things harder for everyone, but to carry it out even farther, we may as well make the code fully immutable since then an attacker wouldn’t be able to do anything to it then. If you disagree with this, then surely you must agree that there’s a balance to be found and it depends on the needs of the organization?
> I mentioned that profitable organizations often secure their applications
Well, I never made the argument against securing applications, but assuming you meant that they use microservices, that’s great, although unfortunately it doesn’t mean anything about the overall appropriateness of microservices. Profitable companies are known for moving so slowly they are unable to adapt to anything even when it means their existence is at stake, and also for blindly following the path laid out for them by laws, shareholders, stakeholders, etc. almost as an automaton without brains. So this supporting point isn’t hugely convincing.
If your point is that in a very specific set of cases, microservices are appropriate, then we are in agreement. However this wasn’t the tone generated by the comments I was replying to.
How do I do a similar stack trace in microservices to understand the path that led to this state? I've used microservices at a couple of companies and their methods were effectively, look at the request id and trace it through this mass of log files for each microservice we are running. It was terrible and could take hours to compile the same information.
What tooling exists to solve this problem with microservices? Genuinely want to know.
Sure, if you are not writing a program using event-driven async style. Every monolith I've worked with has been in async style pretty much.
With global state in the monolith, this can become quite difficult to reason about. By contrast, with microservices, you can analyze the service as performing a small function with a single input and output without global state dependencies. This can be easier to debug.
I've worked on plenty of monoliths with async style code and have found the stack traces to be plenty helpful. It's never been an issue. At least in JavaScript you retain all relevant scoped data and can dump it all if you like. Debugging gets much more interesting when there are no obvious such errors, yet error conditions are present.
I'm still not seeing any equivalent microservice tooling.
Arguably though it’s not special tools is just different tools. You usually can’t run a debugger live in production but with tools like distributed tracing and service meshes you get really close