106

The following commentator writes:

Microservices shift your organizational dysfunction from a compile time problem to a run time problem.

This commentator expands on the issue saying:

Feature not bug. Run time problem => prod issues => stronger, faster feedback about dysfunction to those responsible

Now I get that with microservices you:

  • potentially increase latency of your through-put – which is a production and run-time concern.
  • increase the number of “network interfaces” in your code where there could be potential run-time errors of parsing.
  • can potentially do blue-green deployments. Those could be held-up by interface mismatches (see network interfaces). But if blue-green deployments work then it is more of a run-time concern.

My question is: What does it mean that shifting to microservices creates a run-time problem?

4
  • 15
    If A talks to B in a monolyth at least the actual interface can be proven compatible (through static typing) which makes it more likely it is also correct. Usually microservices communicate over something without such compile time checks Jan 1, 2017 at 14:34
  • If you are studing the problems involving the use of microservices the Fowler article is a must read.martinfowler.com/articles/microservices.html I believe that is not just a case of compile time vs runtime as @Richard Tingle said. And do not really agree that having a production issue is better that one in development. But microservices may help to scale big projects in other ways. (And are an overkill for most small projects)
    – Borjab
    Jan 4, 2017 at 8:36
  • 2
    That commentator is short-sighted. Run time problem => prod issues => unhappy users => lost money.
    – Philipp
    Jan 4, 2017 at 13:52
  • @Philipp: That's the point. Compile time problems caused by organizational dysfunction => nobody cares. Lost money caused by organizational dysfunction => hurts exactly those who are responsible for said organizational dysfunction. The hope: organizational dysfunction gets fixed faster. Sep 5, 2018 at 17:23

5 Answers 5

202

I have a problem. Let's use Microservices! Now I have 13 distributed problems.

Dividing your system into encapsulated, cohesive, and decoupled components is a good idea. It allows you to tackle different problems separately. But you can do that perfectly well in a monolithic deployment (see Fowler: Microservice Premium). After all, this is what OOP has been teaching for many decades! If you decide to turn your components into microservices, you do not gain any architectural advantage. You gain some flexibility regarding technology choice and possibly (but not necessarily!) some scalability. But you are guaranteed some headache stemming from (a) the distributed nature of the system, and (b) the communication between components. Choosing microservices means that you have other problems that are so pressing that you are willing to use microservices despite these problems.

If you are unable to design a monolith that is cleanly divided into components, you will also be unable to design a microservice system. In a monolithic code base, the pain will be fairly obvious. Ideally, the code will simply not compile if it is horribly broken. But with microservices, each service may be developed separately, possibly even in different languages. Any problems in the interaction of components will not become apparent until you integrate your components, and at that point it's already too late to fix the overall architecture.

The No 1 source of bugs is interface mismatch. There may be glaring mistakes like a missing parameter, or more subtle examples like forgetting to check an error code, or forgetting to check a precondition before calling a method. Static typing detects such problems as early as possible: in your IDE and in the compiler, before the code ever runs. Dynamic systems don't have this luxury. It won't blow up until that faulty code is executed.

The implications for microservices are terrifying. Microservices are inherently dynamic. Unless you move to a formal service description language, you can't verify any kind of correctness of your interface usage. you have to test, test, test! But tests are expensive and usually not exhaustive, which leaves the possibility that problems might still exist in production. When will that problem become apparent? Only when that faulty path is taken, at run time, in production. The notion that prod issues would lead to faster feedback is hilariously dangerously wrong, unless you are amused by the possibility of data loss.

17
  • 13
    @JacquesB I am confident that the “organizational dysfunction” refers to the inability to develop a system. The majority of my answer is context to illustrate how one could arrive at such a conclusion, but is my professional opinion and not taken from the tweet.
    – amon
    Jan 1, 2017 at 13:31
  • 10
    "monolith that is cleanly divided into components" - what the hell does that mean?
    – user223083
    Jan 1, 2017 at 22:43
  • 10
    And not to speak of versioning of interfaces (interfaces changing over time). Jan 1, 2017 at 23:17
  • 12
    @mobileink Monolith isn't an ideal term here since it suggests “no architecture”. But what I'm trying to convey is a system that is developed and deployed as a single system, in contrast to a service-oriented architecture where parts of the system may be deployed independently. Please edit the post if you know a better term …
    – amon
    Jan 1, 2017 at 23:55
  • 8
    @amon Hearing the word Monolith doesn't immediately conjure up the idea of "no architecture". Most buildings are Monoliths, as are the Great Pyramids of Egypt, and many other items. Clearly they were architected, and delivered as a whole. Many software systems lack good architecture; but the lack of good architecture seems to be independent of how they are deployed. You may borrow some of the scaffolding of another project and call it the architecture (3-tier, 2-tier, n-tier, microservice, etc.) but doing so doesn't assure you did it well.
    – Edwin Buck
    Jan 3, 2017 at 17:38
222

The first tweet was mine, so I'll expand on it:

Suppose you have 100 developers, working on a monolithic application. That's too many people to communicate effectively between each other, so the company has to work hard to divide them into smaller teams and create good communication patterns between them. When the organisation is "dysfunctional", teams probably aren't talking to each other, they aren't aligned to a larger goal, they disagree on priorities etc - as a result, it takes them forever to ship something. It's a "compile time problem" in the sense that the dysfunction is obvious before the software is produced. The project is probably a death march or never going to ship ("compile").

I think many people are attracted to micro services, and are moving to them, not because of inherent technical/architectural benefits, but because it allows them to ignore the organisational dysfunction. Instead of trying to align 100 developers, they hope that they can have tiny teams working in silos, each focussed on their own little micro service. If you are in such a dysfunctional organisation, this is so attractive: it gives you much greater permission to avoid people you don't like, to not communicate.

Unfortunately it becomes a "run time problem" because once the software is running in production, good communication becomes just as important. The problems with the organisation - the teams and how they are aligned and communicate - manifest at "run time".

The point of my tweet was: if what you have is a people problem, a new architecture isn't going to help. It will just delay the effects of the problem. I think the attractiveness of micro services to many people is the hope that it will magically solve these people issues.

10
  • 69
    +1. This is much better as a Stack Exchange answer than as a tweet. :-)
    – ruakh
    Jan 1, 2017 at 23:31
  • 3
    The same is true for any dynamic systems, really. Dynamic typing is very useful, but only if you have the right people. "Freeform databases" are very useful, but only if you have the right people. If you don't have the right people, you're just delegating the problems, not solving them.
    – Luaan
    Jan 2, 2017 at 9:49
  • 2
    I think this is a tautology. When people are the problem, the problems can manifest everywhere. I cannot imagine shipping a solution running as a set of microservices with out proper integration tests. There is no way of shipping a solution with a supported working flow in such case. If anyone moves to microservices with out flow testing, especially to hide problems, they are the problem. Might as well ship untested/broken binaries. It elevates the problem from trooper-level programmers higher up, where it belongs to.
    – luk32
    Jan 2, 2017 at 16:18
  • 10
    @luk32 In part, yes, but the gist of microservices that make it attractive to bad teams is that you make your skill and communication deficit go unnoticed for a longer period of time. It's not a matter of having the problems or not, is about when they'll show up
    – T. Sar
    Jan 2, 2017 at 17:45
  • 18
    Very nice answer. Thanks for confirming my opinion of Twitter as utterly useless for anything except stirring people up. Jan 2, 2017 at 18:26
43

My question is: What does it mean that shifting to microservices creates a run-time problem?

That is not what those tweets are saying! They don't say anything about shifting to microservices, nor do they say anything about creating problems. They only say something about shifting problems.

And they put a contextual restriction on their assertions, namely that your organization is dysfunctional.

So, what the first tweet is basically saying is two things:

  • "if your organization is incapable of engineering complex systems now without microservices, it won't magically be able to engineer complex systems with microservices" and
  • "the problems caused by that inability which now show up during compile-time, i.e. during development will then show up during run-time, i.e. in production" (technically, they could also show up during testing, but remember, the quote restricts itself to dysfunctional organizations, which likely have a sub-standard testing regime)

The second tweet says that the fact that the problems only manifest themselves in production, i.e. where customers see them, is a feature, not a bug, because when customers complain, that tends to be heard in different places than when a build breaks, namely in places which are able to do something about the organizational dysfunction (e.g. high-level management). Since organizational dysfunction usually is a failure of high-level management this means that unsatisfied customers reflect badly upon those who are ultimately responsible for that unsatisfaction, whereas low code quality caused by higher-level management failures usually only reflects badly upon the developers, who are, however, not at fault and unable to do something about it.

So, the first tweet says that microservices move problems caused by bad management from compile time, where only developers see them, to run-time, where customers see them. The second tweet says that's a good thing, because then, the problems hurt those who are responsible for them.

9
  • 6
    @Michael If you can't see how they impact code quality, perhaps consider what impact -- if any -- management has on any part of the quality of products their business creates.
    – wjl
    Jan 1, 2017 at 17:13
  • 31
    @Michael: Everything is ultimately caused by higher-level management. Is low code quality caused by impossible deadlines? Who sets those deadlines? Who tells those who set those deadlines to set those deadlines? Is low code quality caused by incompetent developers? Who hired those incompetent developers? Who hired those who hired those incompetent developers? Is it caused by inadequate tooling? Who buys those tools? Who approves the budget to buy those tools? It is caused by stupid architecture? Who hired the architect? Who put him in charge? Those tweets were specifically in the context … Jan 1, 2017 at 17:22
  • 15
    … organizational dysfunction. Well, making the organization function is pretty much THE job of higher-level management. That's what management is. Jan 1, 2017 at 17:22
  • 4
    Although it will probably work in the long-term, the idea of solving your company's issues by making them impact customers doesn't seem right. Jan 2, 2017 at 21:48
  • 2
    @JörgWMittag I don't think it's reasonable to claim that bad code written by bad developers is the fault of the people that hired those bad developers and not the bad developers themselves. It might ultimately be the responsibility of management, but it is caused by the developers.
    – Miles Rout
    Jan 3, 2017 at 23:42
9

It creates a run-time problem as opposed to a compile-time problem.

A monolithic app is hard and expensive to compile. But once it compiles you can be reasonably sure that no extremely stupid incompatibilities between components exist, because the type system can catch them. The same error in a system of microservives might not show up until two specific components actually interact in a specific way.

11
  • 9
    This seem to assume "monolithic" applications are always statically typed. What about dynamically typed languages? And what about statically typed service interfaces?
    – JacquesB
    Jan 1, 2017 at 12:39
  • 1
    @JacquesB OTOH, I can think of exactly zero dynamically typed compiled languages.
    – user253751
    Jan 1, 2017 at 13:39
  • 2
    @JacquesB JavaScript and Python aren't compiled. Unless you count internal interpreter structures as a compilation target in which case every language is compiled.
    – user253751
    Jan 1, 2017 at 13:45
  • 3
    @immibis: every single currently existing ECMAScript implementation has at least one compiler. V8, for example, has two compilers and exactly zero interpreters, it never interprets, it always compile to binary native machine code. SpiderMonkey has four compilers, I believe, and one interpreter, but that interpreter doesn't interpret ECMAScript. SpiderMonkey never interprets ECMAScript, it always compiles it to SpiderMonkey bytecode first, which it then may further compile to binary native machine code. All currently existing Python, Ruby, and PHP implementations have compilers. Jan 1, 2017 at 17:26
  • 12
    @LieRyan You are seriously confused if you think type inference is the same as dynamically typed and/or that Haskell is dynamically typed. Jan 1, 2017 at 20:36
2

Both in monolithic systems and microservices you have to define interfaces between the subsystems. The interfaces should be well-designed, well-documented and as stable as possible. This is the same as in OOP.

If your organization is not able to do this, microservices will also not solve the problem. In microservices you have public Web interfaces. So you even have to spend more effort into interface design.

If the interface is not designed properly, you will get two kinds of runtime problems:

  1. If the interface is not used correctly, you will get an error on runtime, not at compile time.
  2. Calling a Web interface is quite slow, so you can get performance problems.

I think producing runtime issues is not the right way communication organizational problems to those which are responsible.

Not the answer you're looking for? Browse other questions tagged or ask your own question.