Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't understand the logic of combining microservices with a monorepo. The whole point of microservices is that you don't care what is beyond the external contract of the service. Who cares how each individual team decides to name their stuff. Why do microservice teams need to care about having every single service checked out? Who or what would be bulk applying changes to all services? This is madness.


Suppose you want to deprecate an API you wrote in favor of something else for $valid_reasons.

In a monorepo with the right tooling, I can make a branch where I delete the API and get pretty immediate feedback as to every module I have broken. From there I can update all the call sites and I also know which teams/engineers I should give a heads-up to.

In a multi-repo world, this is much more difficult. Even learning what all the reverse dependencies are could be a challenge. Most likely, other teams have to pull in my changes on their own schedule, and other teams have very different incentives than my own. The cost of mistakes is therefore higher because they are more difficult to undo.

Monorepos are very important if you want to empower engineers to achieve broad changes across the org. Some people fundamentally disagree with this methodology. And a fair number of people just don’t care enough - marking the old thing deprecated, calling it a day, and letting it rot for eternity is good enough for them. These are the same people who you’ll find saying “not my job” a lot, in my experience.


The perceived ease of that operation in a monorepo is what makes it dangerous. Unless these changes all map to a single monolith service, then even though you have updated all call sites, these callers will not be deployed all at the same time, meaning as the change rolls out you may see random breakage. By using polyrepo, the deployment boundary can align with the code boundary, making the rollout problem obvious.


People point this out often, but in practice I have never seen this cause issues. Remove callers first, then remove endpoint... its pretty obvious the order in which things need to be done.

What I have seen as a real problem, time and time again, is having trouble locating all usages of an API in a multi-repo scenario.

Anyone who fucks this up in a monoreppo will probably fuck it up worse with multiple repos.


I think the tricky issue is updating the structure or semantics of an existent call across services. A monorepo makes it easy to make these kinds of changes in code, while making it non-obvious that it is dangerous to deploy; it is a giant foot-gun. Examples along this line include updating the name of an RPC, or endpoint, or changing the request/response structure, and so on. Of course you could argue that "you just shouldn't", of which I agree, but the point is that then making those kinds changes should actually be really hard, instead of really easy.


Ah yes, this is definitely a challenge. At my day job we use protobuf and follow the (imo well documented and well evangelized) best practice of forbidding breaking changes to protos, so I almost forgot about this class of problem. At least for changes to structure. Changes to semantics can still happen but I don’t know that I’ve ever seen anyone cause a major issue while keeping structures compatible.

We have escape hatches, which I mainly use when deleting code.


Microservices in a monorepo is the least friction path towards a distributed ball of mud.

Whether this is a pattern or anti-pattern depends if you want a single engineer being able to change the entire architecture to “just ship it” or you if you value conceptual integrity more.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: