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

Monolith and Micro-services at different times during the progression of a business can have their places. I have experienced the pains of having to work with both within the same company over 9+ years and here is what I think are forces that can pull you in either direction.

A monolith makes developing initially a lot easier. Over 15 years though, you are bound to have developers of various calibre leave their mark on it. Many don't even understand good modelling and inevitably drive an otherwise healthy monolith with well defined boundaries into a soup of couplings between domain concepts that should not know about each other. In theory though it is totally possible to have micro systems within the same monolith code if you model things that way.

Eventually, your team will flip the table and start thinking how to avoid the problems they are having with the monolith and decide to do down the micro-services way. In most situations developers are likely to face a lack of commitment from the business to spend time/money on a technical problem they do not understand but have to support the development of for a lengthy period of time. Most developers will compromise by building pseudo micro-services without their own databases which send requests to the monolith where the core business logic had to stay.

The benefit of micro-services IMO is driven from being able to separate business domains in a way that keeps each responsibility simple to understand for a new comer and compact enough to not hide a great deal of complexity. It's worth saying this is a very hard thing to achieve and the average developer shop won't have the experience to be able to pull it off.

This is all to say, regardless of Monolith or Micro-services architecture, the key is experience and discipline and without a good amount of both in your team the outcome is unlikely to be a success over a long enough period of time. This is the curse of a business that lives long enough.



In some languages, you can enforce boundaries within a monolith nicely using the build system. The key is to break the build up into a hierarchically structured set of libraries somehow where each library only gets to use those libraries it is allowed to depend on architecturally. Independent bits of business logic would need to go into libraries that cannot "see" each other when they are compiled. Everything would still be part of a single build process and still be linked together into a single big program at the end.

The exact method depends on the language. In C/C++, you'd limit the include paths for each library. In C#, you'd have to compile different assemblies. And so on.


I think you didn't quite get the point of engineers of different levels of quality, talent and opinions working on the same monoliths.

Eventually they tear down any boundary, even those in the build system.

Developer discipline is something that eludes many companies for lack of enough high quality engineers and awareness for the problem in upper management. It's easier to quibble over formatting guidelines.


But the problem with this is it's a technical solution to a social problem.

If your developers are writing crap code in a monolith they're going to continue writing crap code in microservices but now you have new problems of deployment, observability, performance, debugging, etc etc.

As an aside I have a sneaking probably ahistorical suspicion microservices hype happened because people realised Ruby (or similar trendy dynamic languages) often ended up being a write only framework and rather than try and recover some codebase sanity people would rather abandon the code entirely and chase the new codebase high.


> If your developers are writing crap code in a monolith they're going to continue writing crap code in microservices but now you have new problems of deployment, observability, performance, debugging, etc etc.

Anecdotally I witnessed this once. There was this huge ball of mud we had that worked okay-ish. Then the architects decided "hey microservices could solve this", so we started building out microservices that became a distributed ball of mud. Every microservice shared and passed a singular data model across ~30 microservices, which made things interesting when we needed to change that model. Also, we took mediocre developers and asked them to apply rigor they didn't have in developing these services to that they were "prepared" for the failures that happen with distributed systems.

The big upside to management though was that we could farm out parts of the system to different teams on different sides of the planet and have each of them build out the microservices, with each team having different standards as to what is acceptable (what response messages look like, what coding standards should be, ect). All of this was less of a technical problem and more of a managment one, but we felt the pain of it as it was made into a technical problem.


I know. Which is why I have architectural tests that scream if someone uses the wrong module from the wrong place (adds a dependency that isn't what we want).

Of course, any dev could just remove the test, and by that tear down that boundary too. But that test being removed is much more obvious to the code reviewer who would not have noticed the dependency being snuck in. The architectural tests can also contain comments that form a high level documentation of the architecture. Unlike "architectural documents" in the form of some up front word document, this type tends to stay up to date.


interesting, how do you implement such a test?


In .NET I do it om the binaries, I reflect over the assemblies and list the dependencies.

In the same run one can also validate that there are no incompatible transitive dependencies.

Within assemblies (between namespaces) is much harder unfortunately. That means assemblies have to be made to make module boundaries obvious, even though it’s a bit of an antipattern. There are tools such as nsdepcop that watch namespace dependencies, but it’s brittle and a lot of work.


So your argument is that bad developers will mess things up. I am sure most would agree with that argument. What does that have to do with monolith vs. micro-services? Bad developers will make a mess of micro-services as well.


Yes, the original argument was that boundaries can't be enforced. Arguably, it is easier to enforce boundaries between microservices.


You most definitely can enforce boundaries in libraries. Simple make sure that each library can compile and work with only the dependencies available it is allowed to have.


Code review processes should catch the worst of that. If you don't have those and don't have incredibly disciplined developers, well, good luck...


Code review is usually a bad place to catch design flaws, unless it's done early. Usually a bad design means re-doing a lot of the work. That means either getting management buy in or not hitting expected velocity. If not communicated well it can also lead to bad feelings between the writer and reviewer.


Where I work the code review process has mostly broken down. There is just no bandwidth to get anything done beyond the most basic sanity checks. To actually make someone improve their code I'd need the time, energy, authority, good will and probably other things to explain and teach the other programmer what and how to do it differently. But shit needs to get done and if the code works it's hard to convince management why I should invest so much of our time essentially redoing work that doesn't need redoing.

I suspect that this bandwidth problem exists elsewhere also.


If a team is not disciplined/skilled enough to build a well structured monolith the chances they can build and support a microservices solution which is a distributed system with orders of magnitude more failure modes and requires an order of magnitude more tooling and testing is pretty much 0.


> Over 15 years though,...

Correct. That is why the advice not to start with Microservices. Perhaps later may make sense; but not in the beginning.


problem is that often you're to keep going down the path you already started


> Eventually, your team will flip the table and start thinking how to avoid the problems they are having with the monolith and decide to do down the micro-services way.

So, yet another comment saying that modularity requires a distributed system.


That's not what I was saying. I'm saying your team is likely to want to do something drastic and is likely to go down the micro-services path. This is not a comment on correctness. This is a behavioral prediction.




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

Search: