Live data from Hacker News

Monolith First (2015)

martinfowler.com

61–70 of 82 posts

Re: Monolith First (2015)

#61

Earlier quoted context omitted.

There's the ideal path, then the actual. Most monoliths, unchecked and with enough age, turn into spaghetti due to turn over, changing priorities, entropy, etc.

In my experience same goes with microservices. Same spaghetti, different abstraction layer,

you are correct

Re: Monolith First (2015)

#62

Yes. It does require thinking about the monolith in a way so it can be broken up should the need arise. Going down the monolith path != Having spaghetti as the core abstraction. :)

There's the ideal path, then the actual. Most monoliths, unchecked and with enough age, turn into spaghetti due to turn over, changing priorities, entropy, etc.

But at least some microservices architectures turn into macaroni - far too many small, isolated things, with no connection between them. It can have all the disadvantages of an overly-OO design, just at a larger scale.

Re: Monolith First (2015)

#63
Monolith as the final goal is probably a good way to think about the issue.

Janky modular stuff first, full of inefficiencies, few formalities, designed to move fast and _not be in production_. Once it's up and running (in a test setup), you can "see the shape of it" and make it into a more cohesive thing (a "monolith").

This is consistent with how many other crafts older than programming have coalesced over centuries. I suspect there's a reason behind it.

You don't start with an injection-molded solid piece of metal with carefully designed edges that can be broken later (or shaven off) in different ways. You machine something that you don't understand yet using several different tools and practices, then once the piece does what you want (you got a prototype!), you move the production line to injection molding. The resulting mold is way less flexible than the machining process, but much more cohesive and easy to manage.

Of course, programming is different. The "production lines" are not the same as in doing plane parts. In programming you "fly the plane" as soon as it is "air worthy" and does improvements and maintenance in mid-flight. It's often a single plane, no need to make lots of the same model.

So, with that in mind, there's an appeal for carefully planning context boundaries. It's easier to ditch the old radar system for a new one, or replace the seats, or something like that, all during flight.

If the plane breaks down mid-flight, the whole thing is disastrous. So we do stuff like unit testing on the parts, and quality assurance on a "copy of the plane" with no passengers (no real users). Wait, aren't those approaches similar to old traditional production lines? Rigs to test component parts individually, fixtures (that comes from the machining world), quality assurance seals of approval, stress tests.

So, why the hell are we flying the plane as soon as it is barely air worthy in the first place? It creates all those weird requirements.

> When you begin a new application, how sure are you that it will be useful to your users?

Well, I don't have any clue. But _almost all_ applications I ever built were under serious pressure to be useful real fast. Barely flying was often enough to stop the design process, it got passengers at that point so no need to go back to the drawing board. What it often required by the stakeholders is not a better production process, it's just making the barely flying plane bigger.

I know, I know. Borrowing experience from other industries is full of drawbacks. It's not the same thing. But I can't just explain the absurdities of this industry (which are mostly non-related to engineering) in any other way.

All of this reminds me of that "If Microsoft made cars..." joke, but it's not funny anymore.

Re: Monolith First (2015)

#64
post #49

Earlier quoted context omitted.

> Any arguments to support this claim? What's the difference then? The "micro" in "microservice". Microservices are meant to do one "micro" thing well, whether it's image hosting or credit card transactions or supplying the content of a tweet or whatever. A monolith does all the things, or most of the things. It's not "micro". You don't need arguments to support it, these are just the definitions of the terms. It's s…

In my opinion it is too literal understanding of the concept and there is no universal borderline in size or scope. It is common in practice to find quite fat microservices because their maintaners decided it doesn't worth to have yet another network communication latency for a specific case. The main problem here is to be able to effectively debug and maintain several communicating services: to have a distributed tr…

> there is no universal borderline in size or scope

There doesn't need to be. It's applied in specific contexts where the distinction is clear for that context.

You said "A monolith is just one microservice." But it's not, because they're literally defined as opposites. You might as well say "the color white is just one shade of black." It's not adding anything helpful -- it's quibbling over words.

Re: Monolith First (2015)

#65

I firmly believe that monolith vs microservice is much more a company organization problem than a tech problem. Organize your code boundaries similar to your team boundaries, so that individuals and teams can move fast in appropriate isolation from each other, but with understandable, agreeable contracts/boundaries where they need to interact. Monoliths are simpler to understand, easier to run, and harder to break -…

I'm also an advocate of Conway's Law:

https://en.wikipedia.org/wiki/Conway%27s_law

Operationally speaking, it yields solutions aligned with your organization and thus are easier to support.

Plus, I see microservices as a premature optimization. Let it be shown the additional complexity is warranted and provides value.

Re: Monolith First (2015)

#66
I love Martin Fowler's one pager called Snowflake server - it aged very well and I still use it as a reference in the cloud era. And this text is also good advice IMO.

What I feel that is missing on what he calls the "Microservices Premium" is a clear statement that this premium is paid in "ops" hours. That changes the game because of the "ops" resource scarcity.

In fact, the microservices dilemma is an optimization problem related to the ops/dev ratio that is being wrongly treated as a conceptual problem.

This is the simplest analysis I could come up with:

https://logical.li/blog/ops-dev-ratio/

Re: Monolith First (2015)

#67

I firmly believe that monolith vs microservice is much more a company organization problem than a tech problem. Organize your code boundaries similar to your team boundaries, so that individuals and teams can move fast in appropriate isolation from each other, but with understandable, agreeable contracts/boundaries where they need to interact. Monoliths are simpler to understand, easier to run, and harder to break -…

Kind of side steps the fundamental scaling issue though. In a banking app there will be more requests for the account balance than there are logins, but logins will likely take longer. Your argument is more around who is allowed to touch which and who is responsible when it breaks, but not around one of the core reasons to choose microservices.

If you don't want to scale the whole thing (why?), you can also deploy the monolith twice and route different API calls to different clusters. Slice and scale as much as you're willing, paying the price of deployment complexity and bin-packing the usage.

Re: Monolith First (2015)

#68

I firmly believe that monolith vs microservice is much more a company organization problem than a tech problem. Organize your code boundaries similar to your team boundaries, so that individuals and teams can move fast in appropriate isolation from each other, but with understandable, agreeable contracts/boundaries where they need to interact. Monoliths are simpler to understand, easier to run, and harder to break -…

Agreed, in general.

But don't forget about the definition of micro :-) This is an optimization problem rather than a conceptual one.

Re: Monolith First (2015)

#69

Earlier quoted context omitted.

Kind of side steps the fundamental scaling issue though. In a banking app there will be more requests for the account balance than there are logins, but logins will likely take longer. Your argument is more around who is allowed to touch which and who is responsible when it breaks, but not around one of the core reasons to choose microservices.

If you don't want to scale the whole thing (why?), you can also deploy the monolith twice and route different API calls to different clusters. Slice and scale as much as you're willing, paying the price of deployment complexity and bin-packing the usage.

I've been there and done this and it's effective.

It's an imperfect solution for all of the obvious reasons. I think even the most junior engineer could point out the flaws. I won't insult HN readers by naming them!

But also: effective at some things for near-zero cost. It's probably more effective at "segregating your traffic so that Low Priority Service A can't starve out High Priority Service B" than overall scaling but, sometimes that's what you need.

    paying the price of deployment complexity
For us, there was essentially no increase in deployment complexity. There was a small one-time increase in network routing complexity. Essentially requests for "www.foo.com" were routed to one group of servers and requests for "api.foo.com" were routed to another group.

The alternative was decomposing a large monolith. A goal we also pursued. But what you describe was a valuable stop-gap as we undertook that multiyear effect.

Re: Monolith First (2015)

#70

Earlier quoted context omitted.

You scale the whole thing. There's no issue at all.

To what end? To support that 1:10000 transaction that takes the most time and needs the most scaling? Just burn a wad of $20s, that will be easier.

    To support that 1:10000 transaction that takes 
    the most time and needs the most scaling?
Done in the most naive way possible (just adding more servers to one giant pool) yes, it's as ineffective as you say.

What can be effective is segregating resources so that your 1:10000 transaction is isolated so that it doesn't drag down everything else.

Imagine:

- requests to api.foo.com go to one group of servers

- requests to api.foo.com/reports/ go to another group of servers, because those are the 99th percentile requests

They're both running the same monolith code. But at least slow requests to api.foo.com/reports can't starve out api.foo.com which handles logins and stuff.

Now, this doesn't work if e.g. those calls to api.foo.com/reports are creating, say, a bunch of database contention that slows things down for api.foo.com anyway up at the app level due to deadlocks or whatever.

There are various inefficiences here (every server instance gets the whole fat pig monolith deployed to it, even if it's using only a tiny chunk of it) but also potentially various large efficiencies. And it is generally 1000x less work than decomposing a monolith.

Not a magic solution, just one to consider.

Post reply on HN