
Micro-monolith anti-pattern - kiyanwang
http://chi.pl/2017/01/30/Micro-monolith-Anti-pattern.html
======
dasil003
There are a lot of truthy ideas here, but I feel like it still subscribes to
this rosy picture of avoiding the pitfalls and winding up with an amazing
scalable architecture that is an unmitigated win and fundamentally better than
a monolith.

The only problem is that microservices add overhead and require more tuning
and control than monoliths. This is especially true if you give teams carte
blanche to build things however they want with no shared standards.

Being an early stage startup guy I am probably biased, but I would argue it's
best to default to a monolith and try to keep things modular with an eye
towards later extracting microservices as A) you find incongruent workloads
and B) your team is growing and you need to create some isolation so not
everyone has to know everything.

Only once you understand the problem domain and workloads are you fit to draw
service boundaries.

~~~
ethbro
Or to put it another way: There is a time when _every_ feature fits in one
team. There is also a time when any given one _single_ feature grows too large
for one team.

Recognize which time you're in and make the best choice for _now_ (and some of
your expected future).

If everyone designed everything with the expectation of Facebook levels of
traffic, nothing would ever get done (your team isn't big enough), and that
overhead would be wasted in 99.9% of cases.

------
rco8786
> A requirement of a specific framework for all services.

Eh, I don't see this as an antipattern. Building disparate services but using
the same frameworks/languages has tons of advantages and relatively few(none?)
disadvantages.

A few:

\- Engineers can move between teams and features more seamlessly

\- Infrastructure and common functionality can be shared

\- You will inevitably end up debugging someone else's code when it comes to
on-call, that's gonna suck if it looks completely different/foreign to you
than what you use day to day.

~~~
joshdick
Sharing a framework for logging, routing, and other boring things is fine;
sharing a framework with domain-specific logic is when you start getting into
trouble. Now if you want to change something in that framework, you have to
change and deploy every last one of your services.

~~~
root_axis
> _Now if you want to change something in that framework, you have to change
> and deploy every last one of your services._

Do you? As long an appropriate versioning strategy is in place, it seems to me
that you would only need to update the service that prompted the code change,
leaving the other services to use the older version. If the other services
need to have their code changed as well, then that'd be the case whether or
not you used a shared library, except you'd have to update the code in 12
places instead of just one.

------
msluyter
_" Another dangerous decision is to use a lib for reusing code. This is
particularly bad if the lib contains domain logic."_

Question about this: if we're to take the above to heart, doesn't that imply
that we may implement some common functionality multiple times? It seems
there's a real tension here between "code re-use" as a generally laudable goal
and the need to avoid sychronization of testing/deployments.

I'm curious how others out there have dealt with this particular issue.

~~~
optimuspaul
I wrestle with this one all the time. A shared library creates a weak
dependency between the systems that use the library. Making changes to that
library may affect those other systems in unpredictable ways. In my opinion if
you leave business and domain logic out of those libraries and have a well
defined and tested service contract then it is reasonably safe to create
shared libraries. I have found that maintaining backwards compatibility and
using feature flags in these libraries goes a long way at making them
relatively painless for the microservices that use them to deal with change.
We also generally only use shared libraries for codifying best practices and
conventions.

But really, it's a constant struggle. Micro-service teams are semi-autonomous
and are going to recreate functionality at will. That's a communication
problem mostly though.

~~~
lazulicurio
I'm currently struggling with dealing with shared libraries at work. I think
the challenge is that the whole concept of dev-ops is fairly new[1], and from
my experience Java, .Net, Python, etc. weren't designed for easy management of
versioned dependencies. You have tools like Maven, Nuget, and Pip that pop up
because it's a real problem, but they're add-ons to the ecosystem rather than
built-in at a foundational level. And more to the point, if you want to set up
your own package server[2], it can be a huge effort to integrate it into your
build process[3].

[1] Disclaimer: I've only been programming for ~10 years, and professionally
for ~3 years

[2] Personally, I'm currently using Sonatype Nexus

[3] I'm currently grappling with trying to automate building a multi-targeted
assembly .Net assembly, and the co-dependency between VS, msbuild, and Nuget
gives me agita

~~~
diminoten
I can speak best to pip, but versioned dependencies are a non-problem in
Python because of it. Who cares if pip isn't baked into the standard library?

~~~
lazulicurio
Versioned dependencies absolutely still are a problem, even with pip. You
still need something like virtualenv to isolate dependencies for different
projects. And virtualenv is a compete hack (granted, one that works; but still
a hack)

~~~
diminoten
What? Virtualenv is not a hack, and "problem" doesn't mean what you think it
means if you think pip is a "problem".

You're barking up a tree that was cut down a few years ago.

------
pnathan
I'm not persuaded that teams should be this independent. It always leads to a
poor experience for the user. Further, duplicating code and allowing this kind
of hairball growth builds a spaghetti code system, but without adequate
oversight to have sufficient design.

~~~
padobson
This is why a good CTO or VP of Engineering or whoever the team leads are
reporting to is important. Someone has to keep the big picture in mind, both
from a product and engineering point of view. A good leader can guide teams in
the right direction to eliminate bad user experiences or lots of repeating
code or other problems that arise from organizations built around
microservices.

------
xemdetia
This blog post needs proofreading. There is obviously something interesting
they want to talk about but the language is all over the shop!

~~~
scarface74
I agree way too many typos. You can tell it was the lack of proofreading (not
acceptable) not someone whose first language is not English (acceptable).

~~~
bartab4u
It's a .pl address, so I don't think English is his first language.

~~~
scarface74
Now that I read it again, I noticed the sentence structure reads like a non
native English speaker. At first I just paid attention to words that were
wrong that was read like a bad autocorrection.

~~~
kristianc
and that his name is Tomasz Fijałkowski.

~~~
reallydontask
as English a name as John Smith

~~~
kristianc
But one that suggests English might not be his first language.

------
scarface74
I agree with most of the article accept the idea that you shouldn't have a
front facade controller and that each team should be responsible for their own
UI.

That isn't feasible in a lot of real world contexts.

\- what if the same service is used by web and mobile applications?

\- the backend services usually have access to data that shouldn't be exposed
in the DMZ. By keeping all of the services that communicate with backend
systems behind the firewall and having the front end services exposed in the
DMZ, you have another layer of protection with the only port being opened
between the DMZ and the internal network is port 80/443

------
lobster_johnson
This seems to argue that any microsevice shared by many other microservices is
an antipattern.

Lots of apps use S3 as a common store. Is S3 an antipattern? The same goes for
things like SQS, Google Pub/Sub, Google Datastore, etc. In my opinion, the
idea that microservices must be isolated silos is misguided.

There are many things that are top-down (high-level control plane, many small
individual, stateless parts controlled by it), but the opposite of this is the
bottom-up "shared substrate". Things like data storages and buses that have
the responsibility of storing state or shuffling data between actors.

In fact, I consider microservice that's a silo — that is, has its own private
data store — to be an antipattern in many cases. To borrow an old phrase, data
wants to be free. Today's backend patterns are very API-centric, with APIs
acting as awkward gatekeepers to small amounts of data. It's a much better
idea to invert this, Haskell-style: Let the data be first class, and orient
your APIs to work _on_ your data.

------
xg15
I'm not very experienced but the part about (non-)shared front-ends doesn't
sound convincing to me at all. Why are some methods to combine front-end code
bad (angular) but others are good (ESI tags, allegro)? If there is no
coordination between front-ends, how do you get a unified user experience and
a consistent design?

~~~
z3t4
you can have a design document with examples and inspiration.

~~~
xg15
Yes, but why?

This seems to me the same principle as "no libraries, instead keep a spec and
re-implement the domain logic in each service" discussed elsewhere in this
thread.

You _still_ have a common dependency of all services (the spec/design doc) and
you'll still have to modify them all if the dependency changes. Except now you
_also_ have heaps of duplicate code.

~~~
z3t4
It's easy to duplicate code. But hard to delete shared code.

------
rb808
This is a related issue and possible counter example - how do you define
datastructures passed around microservices? Serialized objects ala protobufs?
Versioned XML or JSON? Schema versioned docs?

This is a great opportunity to have shared libraries or at least schemas
across different microservices. In fact having each service write their own
parsers or serializers would be a mistake for me.

~~~
c0wb0yc0d3r
I think you would use protobuff, XML, JSON, etc. The idea would be that you
encapsulate all of your services behind a gateway of sorts. External clients
would interact with the gateway only, and internal services would just provide
a one size fits all response. This way front end teams are responsible for
their clients and there is very little change internally because every base is
covered in the general purpose response.

------
wheaties
I just want to call out that Akka doesn't require you only interopt between
services also using Akka. If it did, it'd lose quite a lot of the benefits you
want to get out of an Actor library. In truth, to interopt or not is a
decision the developers make and it's also a decision they can (should) un-
make.

------
t3soro
> The shared database hidden behind some kind of ACL (anti-corruption layer)
> is a short term solution.

Wat

------
tzakrajs
"That core advantages support quick delivery of new features."

What?

~~~
diminoten
There are a number of typos and misspellings throughout the article, but it's
possible to discern the general meaning anyway.

