[HN Gopher] Build the Modular Monolith First ___________________________________________________________________ Build the Modular Monolith First Author : kiyanwang Score : 85 points Date : 2022-11-13 17:23 UTC (5 hours ago) (HTM) web link (www.fearofoblivion.com) (TXT) w3m dump (www.fearofoblivion.com) | twblalock wrote: | 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? | groestl wrote: | Not only broken up, but merged again after a while as well. | hfjcic7 wrote: | mtkd wrote: | Any team starting with microservices on an unvalidated concept | likely hasn't built a big project from the ground up before | | If it's a small engineering team there is nothing more optimal | than working on a big scappy vertical codebase in the early | stages | | In the fortunate situation you need to start scaling -- breaking | that out into MS later is usually low effort and fun | | If you break it up to early you often end up with logic ghettos | forming in the wrong stack that become near impossible to | relocate later | | I was talking to a startup last year who were hiring several | hundred engineers to build a handful of microservice stacks in | anticipation of the traffic they may get at launch (success | expected because of previous unrelated founder experience), and | wanting to make it easier to deploy vast engineering resource on | it -- they've still not launched anything | eanghel wrote: | > breaking that out into MS later is usually low effort and fun | | In my experience, breaking down 5+ year old / multiteam | monoliths has always been painful, frustrating, and required | huge efforts, especially when nobody remembers why certain | things are the way they are. In addition, getting enough | support for business to do it was hard. I really find it quite | surprising to hear someone share the opposite opinion and | wonder what kind of environment and the size of the project you | were in. | alecthomas wrote: | 100% agreed there. I've never seen this go smoothly, and | usually the monolith lives forever, slowly shedding | functionality but never quite disappearing. | [deleted] | revskill wrote: | The issue is not microservice is complicated. It's about CI/CD | complexity. | janef0421 wrote: | 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 modules | to communicate, if it later becomes necessary to move towards a | micro-services architecture. | KyeRussell wrote: | 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. | eeperson wrote: | 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. | anon23anon wrote: | I 100% agree w/ this and play an enterprise architect type role | at my employer but I would totally get lambasted if I proposed | this. Honestly a lot of the ppl I work w/ aren't developers and | never were. They just have big mouths and climbed the ranks. | Sadly they're the ones who write my reviews and could get me | canned so I have to play ball. | rroot wrote: | Been there, done that, caused a burnout after a long time. | 0/10, wouldn't recommend. Pay was good though. | basicallybones wrote: | 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). You can leverage common libraries without versioning | hell/cross-repo coordination. If you have mediocre developers on | the team and very aggressive development timelines, the monorepo | structure helps enforce modular organization. If you are a good | developer, your workflow gets very, very fast, and you can manage | a lot of complexity. | | Add: additionally, if you have ever-changing requirements and | some are obviously bolt-on one-offs that aren't going anywhere, | you can limit damage to the code quality by splitting those | features into a separate microservices (making it much easier to | safely deprecate/remove them in the future). | twblalock wrote: | 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 is decoupling teams so they can | move independently without blocking each other. | | Also, needing to release the services together, or in a certain | order, is a very bad and unscalable pattern. Teams need to be | able to move independently. This requires a commitment to | avoiding breaking API changes no matter what kind of repo | structure you use -- and for the love of God, never let more | than one service access a database table! A table should only | ever have one service that accesses it, and API boundaries need | to be enforced as the only way other services get to the data. | Do those things and you will be better off no matter what repo | structure you use. | basicallybones wrote: | 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 the people around me had | a commitment to avoiding breaking API changes, but it just is | not so because of aggressive development timelines. 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. | theptip wrote: | The assertion that monoliths are taboo is a bit odd; "monolith | first" has been pragmatic best practice for years: | https://martinfowler.com/bliki/MonolithFirst.html. | mirekrusin wrote: | Exactly, Sam Newman says the same thing in "Building | Microservices" book. | | I don't know where people got this idea but I've noticed the | less experienced, the more noise they make about it. | ch4s3 wrote: | I think this depends on who you listen to, but I'm a huge fan | of the monolith and wouldn't break one up unless I has a | specific tech need(eg some weird library), a performance issue | unaddressable in the monolith, or big organizational people | problem and in that order. | miroz wrote: | Ditto. You should start with a monolith with a vision of how to | break it down into microservices (if ever needed). | | When my company got a contract for a new project, my colleague | created a prototype, a bare-bone solution that had 9 web projects | that communicated over REST, because microservices. I suggested | starting with monolith. Guess whose design was accepted because | it was more sexy. It never got to production for multiple | reasons, but part of it was that development was awfully slow. | Orchestrating changes across services when development is in flux | is extremely hard. | jacurtis wrote: | 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 micro service | to its' specific needs as opposed to "on size fits all" of | monoliths). So yes they can be right-sized in your cloud easier | and have tailored performance, but it comes at the complexity of | the deployment and management of the system. By comparison | monoliths can sometimes be managed without a dedicated | SRE/DevOps/CloudEngineering team. | | Monoliths tend to be cheaper to deploy (up to a certain point). | | Startups should consider building on monoliths more often. For | proof of concept and MVP tools, monoliths are the way to go. Solo | developers also are much better served with monoliths compared to | micro services. But I will say, eventually if you scale big | enough it will eventually make sense to leave monoliths behind | and move towards micro services. Yes there are exceptions | (someone will write, "but XYZ company is worth 9 gajillion | dollars and runs on a monolith), but generally speaking I | consider starting with a monolith and moving to micro services | after you hit market acceptance for your product. | mirekrusin wrote: | 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? | mberning wrote: | I have long running ruby and java apps that I use for this | purpose. They have build scripts, test frameworks, etc. When I | get an idea for something new I add them to one of these existing | projects, but I do it in a way that I can easily excise it in the | future. | plugin-baby wrote: | Megalith! | afhammad wrote: | Curious to hear more. Are these personal projects or serving | users? What are some examples of unrelated ideas you've tacked | on to existing app servers? | BiteCode_dev wrote: | And then on it because you most likely part of a project that | will never have any requirement that needs anything else. | jrochkind1 wrote: | 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! | jameshart wrote: | 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. | KyeRussell wrote: | 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. | jameshart wrote: | 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'. | jolux wrote: | Microservices to me are solving two problems: an organizational | problem and a technical problem. The organizational problem is | more obvious: well-factored monolithic codebases go poorly with | large, interdependent groups of teams. The technical problem is | that while it's true that you can write a monolith in a modular | style, in my experience enforcing the single responsibility | principle in a monolith demands a level of discipline that is | not feasible to maintain indefinitely in an environment with | personnel turnover. When architectural coupling requires making | coordinated changes to multiple services, the barrier is high | enough that people will tend to avoid it instead. | eanghel wrote: | Wholeheartedly agree, I also feel like people are | overestimating how much discipline you can collectively have | in an organization. And if you create a monolith with hard- | enough boundaries to enforce modularization then you might as | well create multiple services (and not necessarily the one- | microservice-per-entity kind of architectures, just as many | as the modules) | vyrotek wrote: | Completely agree! We build our .NET projects in a similar way | too. | | My current SaaS company has 8 web projects and 1 core project. | Some of the web projects are SPAs using BFF and others are APIs | for customers or our mobile app. They aren't tiny sites. We're up | to ~500 controllers. All in a single repo and automatically | deployed as a monolith. We have a super small but very productive | team which we attribute to this simple design. | jjtheblunt wrote: | BFF ? | kroken wrote: | Backend for frontend | vyrotek wrote: | Backends for Frontends. An alternative to making "one API to | rule them all". Far less time spent trying to model an API in | an abstract way that makes sense to many consumers. | | Instead, an API and the endpoints are designed for a specific | client. (e.g. A Mobile App or SPA) For us, this also meant a | more RPC based API where and reusability is managed after the | network hop. | | https://samnewman.io/patterns/architectural/bff/ | rwoerz wrote: | 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? | [deleted] | adra wrote: | 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. | jameshart wrote: | Indeed. Most companies which are cited as 'running the whole | system as a monolith' aren't _really_ a monolith. They don 't | actually run their CMS, their online comment system, their | payment processing, their payroll, their recruitment databases, | their build pipelines, their bug tracker, and their hardware | asset management system, all out of one codebase with a single | RDBMS on the backend. | | People will laugh at that concept, but go look at how mainframe | systems work, and you might be surprised how close some old | banking systems are to that level of monolithicness. There | really are companies who run essentially all of those systems | off a single ERP platform. Or worse, on Sharepoint. | [deleted] | mirekrusin wrote: | 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. | rroot wrote: | During the Covid pandemic, I watched from a distance a group of 6 | people start and destroy a project. | | After the 6 months, they didn't even have a a MVP. | | This was run on a 6 month fund from the local government. They | didn't know each other but they all knew that after 6 months it'd | be over unless they'd secure more funding. | | They spent the time faffing around, configuring things, splitting | things, ... effectively making things harder for themselves. | gw98 wrote: | That's what we're currently working on. | | Only 20% of the work now goes into actually improving the | product. | actually_a_dog wrote: | That may be better than 100% of the work going into improving | the product, taking 1/5 the speed it should. | gw98 wrote: | We're still doing 100% of the work but with 20% of the | quality. | jameshart wrote: | There are more than two architectures. | | I agree if you don't have organizational scale, microservices | solve problems you don't have. | | But there are at least three separate things that are | 'monolithic' about a classical monolith. 1) the codebase, 2) the | database, and 3) the build and release process. | | And you can certainly modularize your codebase into libraries or | independent modules, but retain monolithic builds and releases | against a monolithic relational database - a 'modular monolith'. | | But I'm not sure that's the _interesting_ part to break up, | especially if you are not trying to solve the organizational | problems microservices help with. | | On the other hand, modularizing your build and deployment process | could be helpful even if you are a solo developer - because it | helps you reduce cycle times, and make smaller changes which | means that you can trace bugs more quickly. | | And modularizing data access is better for security and reducing | blast radius of bugs or errors. | | Modularizing the codebase seems much more like a problem you only | need to tackle when your organizational complexity increases. | mind-blight wrote: | Similarly, I feel like microservices are implemented to help | with "scale", but it's often fuzzy which metric is being | scaled. You can scale | | 1. Number of developers in your org 2. Number of users on your | platform 3 Amount of data or compute used | | Not all products need to scale all of these dimensions, and a | microservice architecture may or may not help much. I'd argue | that you probably get better results for #2 by optimizing | database queries and implementing a good catching layer | KyeRussell wrote: | The core question "what is this in service of?" is what | separates good developers from mediocre ones. ___________________________________________________________________ (page generated 2022-11-13 23:00 UTC)