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

> There is still coupling in microservices, it has just shifted to messaging, networking, and queuing.

Sure, in the sense that your service is "coupled" to a queue and if you don't abstract that away it's hard to change that queue implementation. But in the sense of two services you wrote being coupled, they aren't, in terms of shared state. That gets pulled out. There is no way for one service to mutate the memory of another - it has to send a message to it.

That can be TCP or it can be over some queue or stream or whatever.

> If you get any of those parts wrong, you have a worse mess to untangle with less mature debugging/logging tooling than a monolith enjoys

This is the case with any concurrent system. The fact that so many languages lack concurrency primitives is probably why people don't run into this more often. If you use concurrency primitives in your language, you already have this.

> all the while likely dealing with eventual consistency (depending on the design)

There's nothing eventually consistent about this system. It fundamentally has causal consistency (since messages from a service must come after messages to that service that triggered them), and it's perfectly capable of leveraging transactions.

> I'm not saying don't start with a microservice, but it likely wouldn't be the very first tool I would reach for when starting out if a monolith would do the job effectively.

To each their own. I much prefer it. It's far simpler to maintain "good" design since the network boundary creates a hard line in the sand that you physically can not violate.




They are coupled by the queue itself (you accounted for your queue going down and out of order/delayed messages right?), the network (i.e. what happens if some microservices go offline?), and most importantly the event message abstraction. Nothing is for free, and the event message abstraction/format is the new shared state in microservices. It's easy to get the event messaging abstraction wrong in green field projects, since you likely don't understand the domain as well as you would like. If that goes wrong, it can be very painful to fix after the fact. Again, not slamming microservices, but we should go in with eyes wide open about the well-known benefits vs. the tradeoffs they offer. I refer to the high quality (and partially free!) course [1] taught by Udi Dahan from Particular that reviews many of the tradeoffs with distributed system design.

> The fact that so many languages lack concurrency primitives is probably why people don't run into this more often. If you use concurrency primitives in your language, you already have this.

The difference is that with a monolith, the entire application state is in one place, but with microservices its state is distributed. This makes logging and debugging more difficult along several dimensions. Finally, there are decades worth of tooling development at your disposal to debug and monitor your monolith (even concurrency issues). The tooling around debugging and troubleshooting microservices pales in comparison.

[1] https://learn.particular.net/courses/distributed-systems-des...


> That gets pulled out. There is no way for one service to mutate the memory of another - it has to send a message to it.

If it’s well-designed, and that’s a big if. Most implementations I’ve worked with constantly mutate each others’s state.


No, it's physically impossible. You have causal consistency across services, not within services.

https://youtu.be/lKXe3HUG2l4?t=1438


Codebase A writes data to datastore. Codebase B mutates it. Codebase A loads it back in, assuming it’s still the same.

Boom. You’ve mutated codebase A’s memory.


I would hope it's obvious that you haven't mutated A's memory, but I'll just suggest you watch the talk.


How is that any different to calling a function on a class? That's technically not class A modifying class B's memory either. B modifies it's own memory in response to a message (function parameters) from A. The message going over a network doesn't make that fundamentally different.


Function parameters aren't messages. They're shared state. I'd suggest watching the talk and reading about message passing systems in general.


“Watch this famous video” is not a great response. Many of us watched it years ago and seem to have interpreted it rather differently.


Then you interpreted it incorrectly. I'm not inclined to teach you via HN about a subject that's well documented by resources I've already linked.


I suppose if you mutate them. But we have a linter in place and a CI system that enforces it that prevents that.


There are many solutions, certainly. A network is one option, which I personally prefer, but as I said elsewhere it's a "choose the right tool for the job" kind of situation.


For all intents and purposes, you’ve mutated the memory. Sure, you haven’t mutated by reaching directly to the RAM. But the effect is still the same.




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

Search: