Hacker News new | ask | show | jobs
by nurettin 347 days ago
I use multiple services for resilience. Example: With multiple services that have clear separation of concerns, you can debug and fix your processing layer without stopping the collection layer. You can update a distributor while workers wait and vice versa. This way I never have downtime anxiety. No regrets.
3 comments

Separation of services is orthogonal to separation of concerns. There's nothing stopping you from having multiple entry points into the same monolith. I.e. web servers run `puma` and workers run `sidekiq` but both are running the same codebase. This is, in fact, the way that every production Rails app that I've worked with is structured in terms of services.

Concerns (in the broad sense, not ActiveSupport::Concern) can be separated any number of ways. The important part is delineating and formalizing the boundaries between them. For example, a worker running in Puma might instantiate and call three or four or a dozen different service objects all within different engines to accomplish what it needs, but all of that runs in the same Sidekiq thread.

Inserting HTTP or gRPC requests between layers might enforce clean logical boundaries but often what you end up with is a distributed ball of mud that is harder to reason about than a single codebase.

By concern I meant performing different actions and owning write access to different tables, not having completely separate code bases you seem to have construed for some reason.

I would also never connect services without a queue unless the message can be discarded (then I can use a pub sub). Using http is one of the most amateurish ways I can imagine to connect two services that I wrote. Even the thought is cringe. Is this common?

For your example, rails apps handle this case by default with job queues that are managed by the deployment separately. There is a way to force the job queue to process in the same process as your web server, but that's not the way most should be running prod rails apps. There usually isn't anxiety associated with rails app deploys, in my experience.
What can you not do in a monolith? You can still have async queues and different event processors that stop and start independently within a monolithic deployment.
Speaking as a monolith fan, IMO/IME the main drawback is RAM usage per instance.

You can have a "big, beautiful" Rails monolith codebase used by both Puma and Sidekiq queues etc, and that works well from most standpoints. But RAM usage will be pretty high and limit horizontal scaling.

Yep, that's a great point.

Fixing this would probably require some changes at the language level, or at the module-loader level for some languages that use one.

Does it? RAM is not particularly expensive
Sure, you can get 32GB of RAM for less than $100, but that's not the relevant thing to think about.

Think about it from another angle. RAM is expensive when you're talking about cloud infrastructure at scale.

Or, think about it this way.

For a given compute budget, I can run X instances of Rails, or X times Y instances of a framework that uses less RAM. 100 instances of Rails versus 300 instances of Express or whatever.

Now, it still might be worth it to run Rails, because developer time is more expensive than cloud infrastructure. Or maybe you don't really need to scale. Or you could skip the cloud infrastructure and go bare metal, which is what Basecamp does last I checked.

If by monolith you mean multiple processes that you can control separately, each with their own memory state, you can do anything you want with it. That's essentially multiple services.
Monolith architectures are not constrained to running as a single process or on a single machine at all.
Did you just reply to the first word?