Live data from Hacker News

Build the Modular Monolith First

fearofoblivion.com

41–50 of 90 posts

Re: Build the Modular Monolith First

#42
post #4

I think more startups need to consider building monoliths first. Micro-service architecture definitely has the advantage at scale, but the advantage of monoliths is the speed that you can build and improve them. Microservices require much more planning and architecture discussions compared to monoliths. Microservices also can have incredible performance improvements over monoliths (being able to scale or tailor each…

They are better at scale (hundreds of developers or machines needed to run the system).

They are better at avoiding downtime during deployments because everything is built around supporting it - but at huge cost. Offline migrations - which may be taking just seconds/minutes - are so much easier to do. We're talking about order of magnitude difference in complexity of adding new features.

In typescript world, monorepo with shared packages where some are dockerized services (all under same monorepo wide version) is more than enough for most projects. Microservice crowd will call it monolith (because services can't be deployed independently, they likely share SQL database etc), but it's a set of services. You can run it from docker/swarm/k8s - scalability is not really a problem here until you're HUGE (hundreds of developers or hundreds of machines to deploy to). Refactoring, adding new features, dropping stuff etc. - is all easy, usually type checker will guide you to all places that need changing. Single set of migrations. Straight forward e2e. Fast local development where you can spin the whole thing etc. Why people like to complicate their lives when they have this?

Re: Build the Modular Monolith First

#43
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 monolith be successfully 100% broken up into microservices?

Re: Build the Modular Monolith First

#44

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…

Not only broken up, but merged again after a while as well.

Re: Build the Modular Monolith First

#45

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.

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 debug.

Re: Build the Modular Monolith First

#46

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…

Why does the "old monolith" need to be broken up?

I'm all for ending old software when the time comes but not everything needs a rewrite to microservices.

Supporting two development paradigms isn't really a thing any reasonably sized organisation should be concerned about.

Especially when you're talking about adding one more build process to hundreds across all your services.

Re: Build the Modular Monolith First

#47
post #29

The whole monolith vs microservice discussion revolves around a false dichotomy and higly subjective and context-dependend definitions. For example, what if a monolith is integrated into a larger system landscape (e.g. due to an enterprise merger). Is it still a monolith?

A monolithic architecture isn't about being the one and only compute tier. It's about defining how many distinct things that any tier does, which is why microservices go well with partitioned teams. Smaller compute business domains means specialization and easily divisible work functions.

Re: Build the Modular Monolith First

#48
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 start driving again with new wheels. With microservices you need to do it while driving and it's going to be more complicated.

Re: Build the Modular Monolith First

#49

Earlier quoted context omitted.

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.

I’d tell anyone that thought that that it’s a very shortsighted view. If they had started with microservices there’s a good chance the project wouldn’t be around long enough to even go through that transition.

So don't start with microservices. But also don't start with a monolith!

If you have offline batch processes, don't make the mistake of implementing them in the same codebase as your website just because you already have the DB access and build/deploy tooling set up. If you have an admin portal and a public website that listen on different ports, don't run both listeners in the same process.

'don't build microservices yet' does not have to mean 'start with a monolith'.

Re: Build the Modular Monolith First

#50

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…

A monorepo of microservices is the best pattern, but only if you have a dedicated team that keeps the monorepo buildable, builds tooling for it, and enforces best practices and the right culture. If you don’t do that, you will end up with a huge mess — I’ve seen it happen. For companies that can’t dedicate the resources to do a monorepo properly, a repo per team is the best approach. The true value of microservices i…

These are very good points. A few responses:

- The monorepo tooling I prefer at startup scale (NX) does have a learning curve, but it has been pretty easy to maintain using automation (good linting, good build/test pipeline, etc.). For me, learning and leveraging the right monorepo tooling is way easier than having to enforce consistency across large numbers of repos with a small team or watch a low-tooling monolith decay into tightly-coupled spaghetti. I am also in a particular situation where the need for eventual scale is obvious, will come very quickly (clients are big), and the thought of having to rush a scale-inexperienced team (management and devs!) through a monolith-to-microservice migration on a tightly coupled codebase while meeting SLAs is so unpleasant that it makes me a bit sick to my stomach to think about it.

- The monorepo framework/tooling matters a lot. For instance, NX is small-scale friendly and largely can be overseen by senior Typescript devs. Bazel, on the other hand, requires a hefty context switch and has a very steep learning curve.

- You are right that releasing all services together does not scale past a certain point. My point is that microservice monorepos let you pivot quickly between all-together (monolithic) releases and individual app releases as appropriate for your scale. With good caching and parallel blue/green deployments, adding new services to an all-at-once build/deploy pipeline just uses a bit more compute for the pipeline without meaningfully impacting the pipeline run times.

- Having to release services serially in a certain order obviously indicates something is seriously wrong under the hood.

- You are very right about monorepo tooling/best practices, but I would extend that to any project that eventually will need to scale. Someone has to take ownership and enforce good practices. Spaghetti code can be harder to prevent in a feature-heavy monolith and certainly is harder to deal with for me if it is in many different repos (i.e., several monoliths).

- You can have more than one monorepo for teams that are very different or have specific needs (i.e., different languages, mobile apps, etc.).

- I wish I were in a situation where my team could commit to avoiding breaking API changes, but it just is not so because of aggressive development timelines. (I am sure this will change in the future as we scale.) All-together versioning/releasing helps deal with (planned, intentional) breaking API changes very efficiently, because (as long as you can tolerate a failed API call once in a while as a blue/green deployment switches traffic) you're basically performing the deployment as if it is a monolith.

Add: 1000% agree about db access. That is very easy to enforce at the architecture/team level.

Post reply on HN