
The Cracking Monolith: Forces That Call for Microservices - markoa
https://semaphoreci.com/blog/2017/03/21/cracking-monolith-forces-that-call-for-microservices.html
======
icebraining
I find this article lacking, since it paints a too simplified brush over
monoliths. Some missing points:

"Monolith", at least if you define it as a single process rather than a
network of (micro)services, can still be modular in nature. Using a flexible
core, you can build your application as a combination of modules, rather than
as a single large codebase.

They also don't have to be a SPOF: in our architecture, we deploy monolith _s_
, one for each client (ie, company, not user), while keeping them isolated
from each other. This allows us to scale pretty much indefinitely using a
simple architecture. We don't have a huge sharded database, but small bundles
of databases. We don't have datacenter-wide load balancers, rather we allocate
clients to certain groups of nodes and use DNS to point them there.

This works because our clients don't really need to interact with each other,
unlike say, social network users. Do yours? If not, why are you building a
huge and complex mesh of services?

~~~
witheld123
Isn't it hard to maintain all the servers? How do you upgrade your application
or your database?

~~~
icebraining
We automate it :) There's an "inventory" of the current instances, and then
using configuration management (currently Ansible) we can deploy a new version
(running migrations, starting new processes and stop old ones, etc) for all or
any subset of our instances with a single command.

------
romanovcode
Author without even knowing it described common microservice architecture
problems that are faced in front-end. (Because in microservices front-end is
consuming API and is usually a SPA)

\- The single point of fragility

Yeah, if you have an js error in your syntax the whole front-end application
will not work.

\- Slow CI

Actually the front-end nowadays is the bottleneck of any CI if it is using
React/Angular2 because of all the tree-shaking and optimizations. It can take
a good 8 minutes to build, optimize, tree-shake, AOT etc. a modern SPA
application.

\- Slow development cycles

This has nothing to do with monoliths whatsoever. If your codebase is crap it
doesn't matter if it's microservices or monolith.

Anyway, I digress since this is a textbook Mary blog article.

~~~
viach
\- Yeah, if you have an js error in your syntax the whole front-end
application will not work.

How is this possible that you compiled js code with an error during packaging?
Or you don't use packaging/analyzers tools?

~~~
ec109685
If you reference a null object, an exception is thrown.

------
elvinyung
I would like to argue that a microservice architecture is frequently a
response to the scalability limits of traditional databases. Decomposing a
monolith into multiple services (with each service interacting with only its
own database) is essentially a form of vertical partitioning. It's a way to
delay sharding.

Microservices are nice, but they seem like a heavyweight way to "force" module
boundaries to exist. Potentially, if database technologies improve, there
might not be a need to split up a monolith until much later on.

~~~
mtkd
the danger in my view is that it is seen as a binary choice - which, if you go
all in on microservices, just shifts from one problem to another - they need
to be seen as just another tool for architecting and scaling

there is nothing wrong with building a monolith so long as you gave some
thought to how it might get partitioned later

once you've built a few I think you start to see where those pressure points
will be and microservices are a good pattern for scaling the functions that
get all the traffic once it's working

I hear people talking about using only microservices to underpin a big app but
I just can't imagine that is an efficient or sustainable approach for an app
with any complexity if the core function spans across all those services - at
the very least I can see macro changes becoming disproportionately more
challenging and risky over time

~~~
dragonwriter
> I hear people talking about using only microservices to underpin a big app
> but I just can't imagine that is an efficient or sustainable approach for an
> app with any complexity

Not having some coherent analytical approach probably isn't efficiently
sustainable for complex systems, but if you have one, microservices for the
whole system probably aren't a problem, since most system analysis approaches
end up describing/modeling systems in a way that has a natural corresponds to
a set of microservices wired together with a messaging bus.

------
ex_amazon_sde
> early adopters have been tech behemoths such as Amazon

Not true. Amazon is heavily service-oriented, but quite wary of _micro_
services. You need the right size - microservices are often too slow and
require a lot of work to debug.

~~~
treehau5
The term micro was always left up to the implementer to define what exactly
constitutes micro. There is no uniform standard, and no official definition of
microservice, and indeed in my own short time dabbling in them, I have seen it
vary from org to org.

The ultimate example I have seen, and used myself, is an AWS lambda function,
but even then you talk to some "microservice experts" and they don't consider
this to be the case.

~~~
jsudhams
hmmm i always thought there is clear definition. So microservice is :

A smaller problem domain. Built and deployed by itself, running in its own.
Runs in its own process. Integrates via well-known interfaces. Owns its own
data storage.

[https://youtu.be/wgdBVIX9ifA?t=13m10s](https://youtu.be/wgdBVIX9ifA?t=13m10s)

What is micro services [https://github.com/msjaiswal/book-
notes/blob/master/Building...](https://github.com/msjaiswal/book-
notes/blob/master/Building%20Microservices.markdown)

* copied from stack overflow

~~~
treehau5
I have a copy of the book you linked in the book-notes! I am excited to start
reading it. It's funny you bring up that book because I arrived at my
conclusion that how small "micro" is in microservice is based on my previous
viewings of talks and articles by Sam Newman and Fowler. I think a lot of
microservices are is just applied distributed versions of Enterprise
Integration.

------
douche
> Emergency-driven context switching: we may have begun working on a new
> feature, but an outage has just exposed a vulnerability in our system. So,
> healing it becomes a top priority, and the team needs to react and switch to
> solving that issue. By the time they return to the initial project, internal
> or external circumstances can change and reduce its impact, perhaps even
> make it obsolete. A badly designed distributed system can make this even
> worse — hence one of the requirements for making one is having solid design
> skills. However, if all code is part of a single runtime hitting one
> database, our options for avoiding contention and downtime are very limited.

Flying Spaghetti Monster, this has been my life for the last three months.
React, react, react. Spend two days working on new features, spend the next
three on emergency bugfixes for old releases, rinse and repeat.

I'm so ready for a vacation.

------
Toenex
I'm not sure what we (bioxydyn) have done constitutes a microservice but we
have split different parts of our business logic into separate executables
that communicate using HTTP and a central data store. Our product is a data
processing pipeline and we took this approach for several reasons which I may
have missed in my skim read of the article. Firstly different parts of the
pipeline have different resource requirements and would thus be hosted on
different hardware configurations. Also parts of our pipeline lend themselves
to different designs and languages (some Java, some C++) decisions which are
also influenced by the availability of third-party libraries. Finally, by
designing the overall system as a set of coordinated individual services we
allow greater flexibility in our deployment model; allowing us to cope with
some unknowns around scaling and regulations in different environments.

~~~
taneq
I'm no microservice expert but I'd guess the difference between your approach
and microservices is that multiple instances of a microservice run
concurrently, so they're inherently easier to scale?

------
dyeje
A CI company that charges per box trying to persuade you to get more boxes.

~~~
markoa
Consider a contrary argument. If every app in the universe was composed of
microservices that do one thing and test out in 5 seconds, then there'd be no
need for CI, only monitoring & continuous deployment.

~~~
snovv_crash
Because everyone knows that the "ops" part of devops is the part that is
enjoyable and scales well. /s

On a more serious note, if that is the goal why not just write a monolith in
Erlang? You can hot-patch functions, scale on multiple machines, and don't
need to use http as IPC.

------
colemorrison
I wonder how much criticism and hatred this post would've received had it not
used Rails as the example case. Monoliths exist in other stacks (obviously),
but the Rails community always seem to take offense first. This is the first
time I've seen such an opposition to micro services (maybe I'm not looking
through forums hard enough).

~~~
chrisan
> This is the first time I've seen such an opposition to micro services

Like anything, use the right tool for the job and weigh the trade offs

[https://martinfowler.com/bliki/MonolithFirst.html](https://martinfowler.com/bliki/MonolithFirst.html)

[https://www.martinfowler.com/microservices/#when](https://www.martinfowler.com/microservices/#when)

------
whalesalad
Everyone is hating on this post -- for good reason -- but keep in mind that
this is an inbound marketing post for a CI company. It's in their best
interest to have you split your app into many standalone pieces which will
each require an individual testing setup.

~~~
markoa
CI resource-wise, splitting things is actually more beneficial for customers
than vendors. Gives more throughput.

------
skyisblue
Would a microservices architecture be feasible for a team of 3 developers?

It seems like only larger companies are adopting this architecture.

------
sriram_iyengar
Another aspect to consider is, time taken to run regression and automation
tests on the Monolith, by both devs & QAs. This affects frequent release of
software considerably l.

~~~
icebraining
That's because you're testing the monolith end-to-end, but testing the
microservices individually. None of this is inevitable: you should still test
the microservice network as a whole, and you can definitively test the
components of a monolith individually.

~~~
sriram_iyengar
Agree that the functionality needs to be tested in-whole. But the delta in
time is very large when the feature level tests have to be run on the monolith
& they can be avoided when they are tested on the micro service.

~~~
ProblemFactory
But where does the difference come from?

A "well-designed monolith's" code architecture would be very similar to
microservices - with separated modules, but in-process function calls instead
of remote API calls.

If you do large-scale integration tests that cross module boundaries in the
monolith, then you should also have the same tests of the full deployment with
microservices. If you test each microservice independently, then you could
also run tests for each module independently.

~~~
sokoloff
My experience (sample size of 1) is that long-lived monoliths tend not to
evolve along "well-designed" lines, but rather along "what can I possibly do
to get this to work in the time I have?" lines. Further, it's an impossible
hurdle to schedule big dig to make substantial architectural improvements on a
large monolith, so refactorings and improvements tend to be shallow and
localized.

A decade later, and you have a lot of business logic in stored procedures in
your database and now hear grumbling from coders who don't know or don't want
to learn SQL. (And, to be fair, it does make it harder to scale the
engineering team if everyone needs to be proficient at SQL.)

Neither availability nor technical scaling concerns were the reason we started
to transition away from our monolith. We were regularly hitting 4 nines of
availability (measured by "orders coming in") and had scaled to well over $1BB
in revenue essentially on a single database for most of the site
functionality. Above average engineers and ops, and way above average DBA team
was key to making that happen.

------
orless
I'm working on a large system with is based on microservice architecture. We
primarily use microservices to decompose the system into modules and enforce
module boundaries. Things like scaling or performance is not so much of the
problem, the monolyth would most probably work just as well.

Technically we write Spring Boot-based microservices which mainly exchange
messages over RabbitMQ and in some rare cases call REST interfaces of each
other.

Below a few problems I have with this architecture:

* Code duplication. For instance, we have to implement more-or-less the same DTO on both sending microservice as well as receiving microservice.

* Refactoring across microservices takes a lot of effort. In several cases we didn't cut in the right places and had to move functions across microservices. That was always quite difficult, and we also had to implement migration routinges (for databases as well as unprocessed messages which may be still in queues).

* Versioning and synchronization of messages. Our system receives events from the number of external data sources which trigger processing in the microservices and finally produce results. Since message exchange is asynchronous, older messages may overtake newer messages so we have to version them in order to not output obsolete results. Another problem is that messages travel different paths in the system, so it may happen that a microservice receives two messages which are based on partially obsolete data. Consider two sources A and B which produced events a0, a1, b0, b1. Later in the system a microservice receives two messages p and q based on p(a0, b1) and q(a1, b0) respectively. These messages are not compatible and cannot be processed together. But in order to detect this we have to track version of incoming events (a0, a1, b0, b1) all along the processing.

* A hell to debug. At the moment we have a network of around 40 microservices which process data from ca. 6 sources and feed 3-4 receiving systems. Microservices are quite complicated, the work with often incomplete or incorrect data, employ a lot of heuristics and make a number of assumption which are sometimes proven wrong. If any of the receiving systems report a problem we have pretty hard time identifying which of the few dozen microservices failed. Reasoning about asynchronous message processing is very difficult and approaches like remote debugging actually change the behaviour of the system.

* Tools. We employ maybe a dozen of different tools and custom scripts solely for the purpose of configuring, deploying and running our microservices. We'd most probably only needed a small part of them for a monolytic system.

From the other hand our system is a fourth attempt to solve a very difficult
and important problem for our company, the problem which persisted for more
than 30 years. And it is the first attempt which is so far successful.

