Live data from Hacker News

Modules, not microservices

blogs.newardassociates.com

581–590 of 671 posts

Re: Modules, not microservices

#581

I suspect that most people would be better off favoring inlined code over modules and microservices. It's okay to not organize your code. It's okay to have files with 10,000 lines. It's okay not to put "business logic" in a special place. It's okay to make merge conflicts. The overhead devs spend worrying about code organization may vastly exceed the amount of time floundering with messy programs. Microservices aren'…

> It's okay to have files with 10,000 lines. Ever since my time as a mathematician (I worked at a university) and using LaTeX extensively, I never understood the "divide your documents/code into many small files" mantra. With tools like grep (and its editor equivalents), jumping to definition, ripgrep et al., I have little problem working with files spanning thousands of lines. And yet I keep hearing that I should di…

If you change 1 .c file, your compiler needs to recompile the .o file for that file and link it with the unchanged .o files.

If you have everything into one .c file, you need to recompile the whole thing every change.

Re: Modules, not microservices

#582

Earlier quoted context omitted.

What if I have $500/month to spend and still need high reliability and redundancy?

That's a budget for a local crafts store website hosting, not "high availability" system

> That's a budget for a local crafts store website hosting, not "high availability" system

I'm not sure about that: you could still put something together within that budget, say, a few different VPSes across Hetzner and Contabo (or different regions within the same provider's offerings), with some circuit breaking and load balancing between those. Probably either a managed database offering, or a cluster of DBs running on similar VPSes.

Of course, this might mean that you have 1-3 instances of a service instead of 10-30, but as long as availability is the goal and not necessarily throughput, that can go pretty far.

Re: Modules, not microservices

#583
post #569

Earlier quoted context omitted.

Most features in a modern app are not critical functionality, though. For instance, in a shopping site, why should a crash in the recommendations engine result in a non-functional webpage (rather than a working purchase page with no recommendations)? Personally I think microservices start to make sense when you have several hundred developers (an environment I'm currently keen to never enter again - $work has 5 devs…

That makes sense. I am still trying to understand why does it differ between a monolith and microservices. The app in the monolith can make the call to non-critical functionalities time-limited and fault-tolerant, just like a network call has a time-out and can return nothing (in a simplified manner, it can wrap that call with a timer and an exception handler). I agree that microservices are suitable for large organi…

If your monolithic service OOMs, hits a large GC pause causing dependent requests to time out, locks a shared file descriptor, or a bunch of other things then the monolithic service as a whole can hit a fault or stall even if other threads/tasks are still executing. While classes of errors like OOMs go away when multiple processes are executing.

Re: Modules, not microservices

#584
post #98
post #73

I am working on a project that uses a microservice architecture to make the individual components scalable and separate the concerns. However one of the unexpected consequences is that we are now doing a lot of network calls between these microservices, and this has actually become the main speed bottleneck for our program, especially since some of these services are not even in the same data center. We are now attem…

> one of the unexpected consequences is that we are now doing a lot of network calls between these microservices Not trying to be harsh here, but not expecting an increase of network call in a system where each component is tied together with... network calls sounds a bit naive. > We are now attempting to solve this with caches and doing batch requests So you have built a complex and bottle-necked application for the…

Scalability is not a feature. If you "need" to scale but don't then you're not delivering to your target market, not delivering is not a lack of a feature it's a net loss to the organization. If you're Twitter/Instagram/Uber/whatever you cannot tell your users to not post or like or request a ride because "right now we don't have the scalability feature"

Re: Modules, not microservices

#585
post #418
post #72

Microservices, while often sold as solving a technical problem, usually actually solve for a human problem in scaling up an organization. There's two technical problems that microservices purport to solve: modularization (separation of concerns, hiding implementation, document interface and all that good stuff) and scalability (being able to increase the amount of compute, memory and IO to the specific modules that n…

> A better rule is for one service to own writes for a table, and other services can only read that table, Been there: how do you handle schema changes? One of the advantages that having a separate schema per service provides is that services can communicate only via APIs, which decouples them allowing you to deploy them independently, which is at the heart of microservices (and continuous delivery). The way I see it…

For us, we started off with a world where each service communicates to each other only via RabbitMQ, so all fully async. So theoretically each service should be able to be down for however it likes with no impact to anyone else, then it comes back up and starts processing messages off its queue and no one is the wiser.

Our data is mostly append-only, or if it's being changed, there is a theoretical final "correct" version of it that we should converge to. So to "get" data, you subscribe to messages about some state of things, and then each service is responsible for managing its own copy in its own db. This worked well enough until it didn't, and we had to start doing true-ups from time to time to keep things in sync, which was annoying, but not particularly problematic, as we design to assume everything is async and convergent.

The optimization (or compromise) we decided on, was that all of our services use the same db cluster, and that if the db cluster goes down, it means everything is down. Therefore, if we can assume the db is always up, even if a service is down, we consider it an acceptable constraint to provide a readonly view into other services db. Any writes are still sent async via MQ. This eliminates our syncing drifting problem, while still allowing for performant joins, which http apis are bad at and our system uses a lot of.

So then back to your original question, the way that this contract can break is via schema changes. So for us, since we use postgres, we created database views that we expose for reading. And postgres view updates are constrained that they must always be backwards compatible from a schema perspective. So then now our migration path is:

- service A has some table of data that you like to share

- write a migration to expose a view for service A

- write an update for service B to depend upon that view

- service B now needs some more data in that view

- write a db migration for service A that adds that missing data, but keeping the view fully backwards compatible

Re: Modules, not microservices

#586
A benefit of microservices is that you can use specialised languages for different parts of the system. The core of your system might be written in Java but you might one to use Python for an ML heavy module. Nonetheless, I tend to agree that in an organisation with 100 microservices probably the ideal way would be to have 4 or 5 based on exceptions where you have modules that need a specific hardware profile (e.g. a lot of RAM) or a different programming language than your core system. Everything else could go into modules in a megaservice.

Re: Modules, not microservices

#587
post #543
post #431

Earlier quoted context omitted.

Another way to look at this is microservices reduce the blast radius of problems.

How so? If functionality A is critical to functionality B, how will wrapping it in an HTTP call (microservices) reduce the damage from breaking functionality A? I can see an advantage regarding resource hogging, but the flip side is the extra point of failure of network calls in microservices. Not saying which is better, but deployment is orthogonal to logical dependence and correctness.

Resource hogging is a huge class of errors, though. Everything from a bad client update DDoSing a feature, file handles, memory leaks, log storage (a little outdated now perhaps), and so many more...

Re: Modules, not microservices

#588
post #98

Earlier quoted context omitted.

> one of the unexpected consequences is that we are now doing a lot of network calls between these microservices Not trying to be harsh here, but not expecting an increase of network call in a system where each component is tied together with... network calls sounds a bit naive. > We are now attempting to solve this with caches and doing batch requests So you have built a complex and bottle-necked application for the…

Scalability is not a feature. If you "need" to scale but don't then you're not delivering to your target market, not delivering is not a lack of a feature it's a net loss to the organization. If you're Twitter/Instagram/Uber/whatever you cannot tell your users to not post or like or request a ride because "right now we don't have the scalability feature"

I don't completely agree here.

Yes, if you can't scale fast enough as you need to, it can hurt your business. Not being able to keep up with demand is a (luxury) problem that every business faces, not just in tech. They would often be called 'growing pains' in a business, and though they are bad, they rarely contribute to the failure of a company.

Starting a startup/service/platform with microservices before you even understand the bottlenecks/market fit/customers is usually not a good idea. You can come a very, very long way with a monolith before you hit performance and scalability limits. And once you do, you can always start breaking things up into smaller services for scalabity. Obviously you need to make sure you are scaling on time to keep up with demand.

'Nail it, then scale it', and 'premature optimization is the mother of all f-ups' are popular sayings for a reason.

Re: Modules, not microservices

#589
post #197

Earlier quoted context omitted.

I think that's a reasonable heuristic, but I'd also say you have to take into account the human readability aspect of it. It sometimes does make sense IMO to split solely for that, if it allows you to "reduce" a complicated/confusing operation to a string name, leading to it being easier to understand at a glance.

Shouldn't split MegaFunction into Func1 and Func2, you should: MegaFunction() { Func1(); Func2(); ... FuncN(); } People will call MegaFunction() but it will be logically split internally.

This is how it's taught in school but the argument is that you shouldn't do that, instead just inline Func1 and Func2 and comment it better.

By chopping up MegaFunction like this, you've not actually separated Func1 and Func2 if they aren't really independent, they're just MegaFunction in disguise but now split across two places making it more difficult, not easier, to reason about.

If you need the state (implied or explicitly passed in and out) from having executed Func1 to run Func2 then you're just creating spaghetti code. You're taking a big ball of mud and smearing it around instead of actually tackling the abstraction.

This is how you end up with Func(a, b, c, d, &e, &f) which ends up changing your MegaFunction state.

Or just as bad, Func1,2,N are all private functions, never called anywhere else outside the class MegaFunction is in, so logically (and from the point of view of testability) it's no different to having them all inline.

If you're creating a function that's only ever called once, then instead of a function call you're probably better off with a comment to "name" that block and explain the process instead.

Re: Modules, not microservices

#590
post #72

Microservices, while often sold as solving a technical problem, usually actually solve for a human problem in scaling up an organization. There's two technical problems that microservices purport to solve: modularization (separation of concerns, hiding implementation, document interface and all that good stuff) and scalability (being able to increase the amount of compute, memory and IO to the specific modules that n…

I’d love for a language / framework that allows for an application to be composed of “modules” that can either be run in a single process, or deployed as multiple independently scalable processes, with a mostly transparent RPC system requiring minimal boilerplate.

My IDE should be able to easily traverse the call graph. My development environment should be simple to setup.

I’ve worked on microservices that required an insane amount of boilerplate to do simple things. Like 7 layers of controllers, clients, services, data services, etc, just to fetch a simple piece of data. And the developer experience of running dozens of services in a Kubernetes cluster running on my dev machine was awful.

Does anything like this exist?

I only dabbled many years ago but Erlang/OTP comes to mind.

And tRPC for TypeScript calls in browser and server.

Post reply on HN