Live data from Hacker News

Build the Modular Monolith First

fearofoblivion.com

81–90 of 90 posts

Re: Build the Modular Monolith First

#81
One of my first ever blog posts actually was about modular monoliths: https://blog.kronis.dev/articles/modulith-because-we-need-to...

On one hand, monoliths will always be simpler to work with, at least until some point in time where their complexity grows to a point where working with them is a drag on everyone's morale and productivity.

Depending on how they're built, they could still scale horizontally, unless you've written a "singleton" application where having more than one instance and routing traffic between those would break something.

I'd say that a lot of the benefits of microservices and adjacent approaches are actually cultural: having multiple decoupled components lets you focus on whatever the "main" ones are at any given point in development, mostly doing maintenance work on others, whilst still limiting breakages.

And should it come to pass that some of the more boring components will eventually rot away (e.g. be stuck on JDK 8 or Python 2 or whatever) and will need to be rewritten based on what EOL you might run into, then you can mostly do that without affecting the rest of the system. The opposite also applies - you can upgrade 9 out of 10 components to JDK 11 even when one cannot be upgraded, instead of that one module holding everything else back in some monolithic system.

That said, there are lots of complexities to microservices and it's easy to mess things up - I've seen projects where I'm the first person that figures out that some shared code should actually be a Maven/pip/npm package in Nexus/Artifactory instead of just copying and pasting code across codebases, because nobody has put in the work to set everything up properly before me. Don't even get me started on day 2 concerns like tracing and debugging, which the article touches upon.

Other times, even modular monoliths might run into issues because people aren't good enough with writing decoupled code without too many common dependencies (unless forced by the language and its mechanisms to have proper separation), or aren't up to par with utilizing feature flags and such properly.

I think that at the end of the day, all code rots and eventually is hard to work with, which also affects entire frameworks or even languages: https://earthly.dev/blog/brown-green-language/

Your architecture will sometimes have concrete technical benefits or characteristics to take into account, but a lot of the time most of the actual effects will be organizational - how you will or won't be able to build everything, who will be responsible for what and what risks any particular deployment or version bump will carry.

Re: Build the Modular Monolith First

#82

This is written like it's a novel take bucking the trend, but I feel like most things I have seen on this topic for at least several years now have the same observations and conclusions? If anyone wants to actually speak up for microservices, I feel like that's what needs a defense at this point!

I think anyone who has taken a large monolith through a significant platform version upgrade or change, like .NET 2 to .NET 4, or Python2 to Python3, or Angular to React, would need a very persuasive argument to make them believe that starting a new project with a monolithic design was a good idea.

As someone who has done this, both for version upgrades and for substantial refractors of the codebase, I have to prefer monoliths. Atomic commits are cheaper than adding and releasing version support across a system that doesn't have it.

Re: Build the Modular Monolith First

#83

You can try to build a monolith that is modular enough to break up later. But I have never seen it happen, and I’ve been around for a while now. What actually happens, 100% of the time in my personal experience, is that you end up with both the old monolith and new microservices, the monolith never gets fully broken up, and now you need to support two development paradigms forever. Has anyone here ever seen a monolit…

> you end up with both the old monolith and new microservices, the monolith never gets fully broken up, and now you need to support two development paradigms forever.

It's not a bad thing, it's actually a quite pragmatic approach. Some folks call it The Citadel:

https://m.signalvnoise.com/the-majestic-monolith-can-become-...

Building monolith is the best way to learn about domain and domain boundaries. Monolith is way more forgiving for your mistakes.

Going all in on microservices is like believing you learned everything there is. Some folks believe that, most of the time they are wrong.

Re: Build the Modular Monolith First

#84

I think an important thing to keep in mind when discussing monoliths or Microservices is that you can build modular code without needing multiple binaries, processes, or server instances. If you follow best practices when creating a monolith, creating well-defined modules with clear input and output boundaries, then it should be relatively easy to split those modules into separate programs and create ways for those m…

I think a (but not the only) central conceit of a microservices architecture is that most development teams cannot be trusted to maintain proper separation of concerns, and enforcing at a technical level the inability to call Any Old Function is a big part of what you’re buying into.

Most compiled languages will allow a project to be split into multiple modules, and an `internal` access modifier can then be used to limit the use of an element to that module.

Re: Build the Modular Monolith First

#85

Microservices vs. monoliths is a false dichotomy in the present day. If you put microservices in a monorepo with a good build tool (like NX), put the common auth/logging/types/dtos/etc. functions in reusable libs, and version/release all the apps together, you get the best of both worlds. At a small scale, you can deploy your whole containerized stack on two big HA instances (monolithic infrastructure, so much easier…

Isn't that just a monolith with super slow function calls?

Re: Build the Modular Monolith First

#86
I would go much further:

Don't build a modular monolith first, build a spaghetti monolith first.

You need to not die. That's your first prioritization. A "modular monolith" like the article talks about is still worrying about success. You should worry about failure!

Re: Build the Modular Monolith First

#87

Earlier quoted context omitted.

> If you put microservices in a monorepo (...) What exactly do you gain with this approach, other than pinning versions of all microservices? Any competent team working on services does not suffer from "versioning hell" because APIs are stable and tracked with integration tests and smoke tests, and you version the API and not the code.

It vastly reduces the complexity of things like dependencies, testing, CI/CD, versioning. Dependencies can be relative paths. Relative path dependencies will break the build on your machine, so you don't get devs pushing broken stuff. CI/CD servers don't get plugged up with billions of repos building because one changed. CI/CD servers don't need to wait for other builds to finish and push artifacts to do their job. T…

> It vastly reduces the complexity of things like dependencies, testing, CI/CD, versioning.

Did it, though?

The only conceivable advantage is version pinning. I makes absolutely no difference in terms of test coverage whether you use a monorepo or not. Dependencies-wise, the only thing that a monorepo saves is releasing individual components, which ultimately is not an advantage but a drawback and a liability.

So exactly what's the upside, if any?

Re: Build the Modular Monolith First

#88

Microservices is too catchy name. It somehow implicitly means to people less complexity, but the reality is quite opposite. They should be called "a lot of little monoliths that we have to make always running and compatible with each other when updating" would reflect more appropriatelly what it is. Good analogy is replacing wheels for better ones while driving. In non microservice system you stop, change wheels and…

Imo there's a huge distinction between microservices in a monorepo or microservices where there are 100s or thousands of git repos.

Monorepo can be much easier as you can at least verify the given build is consistent.

Monoliths don't completely avoid the problem of version compatibility, they just reduce it to a more clear layer of external clients and compatibility between N-1th release and Nth release. That's certainly worth it in the early stages of a project

Re: Build the Modular Monolith First

#89

Earlier quoted context omitted.

It vastly reduces the complexity of things like dependencies, testing, CI/CD, versioning. Dependencies can be relative paths. Relative path dependencies will break the build on your machine, so you don't get devs pushing broken stuff. CI/CD servers don't get plugged up with billions of repos building because one changed. CI/CD servers don't need to wait for other builds to finish and push artifacts to do their job. T…

> It vastly reduces the complexity of things like dependencies, testing, CI/CD, versioning. Did it, though? The only conceivable advantage is version pinning. I makes absolutely no difference in terms of test coverage whether you use a monorepo or not. Dependencies-wise, the only thing that a monorepo saves is releasing individual components, which ultimately is not an advantage but a drawback and a liability. So exa…

what is the upside of separating them?

Re: Build the Modular Monolith First

#90

Earlier quoted context omitted.

This always seemed strange to me. If your team can't be trusted not to make spaghetti in a monolith, what stops them from making distributed spaghetti in microservices? In theory the extra work of making an API call would give you smaller bowls of spaghetti. However, once you add some abstraction to making these calls it seems like developers are empowered to make the same mess. Except now it is slower and harder to…

> This always seemed strange to me. If your team can't be trusted not to make spaghetti in a monolith, what stops them from making distributed spaghetti in microservices? It's far harder to update multiple services to handle requests they should not handle, let alone update a deployment to allow those requests to happen. Walls make great neighbors, just like multiple services make teams great at complying with an arc…

> It's far harder to update multiple services to handle requests they should not handle, let alone update a deployment to allow those requests to happen.

I'm not sure I follow this. Doesn't this just mean that it is harder to make changes? Why would it be harder to make bad changes and not harder to make good changes?

> Walls make great neighbors, just like multiple services make teams great at complying with an architecture constraint.

I'm not sure I follow this either. Why would multiple services make teams great at complying with an architecture constraint?

Post reply on HN