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?

amon
  • 132,749
  • 27
  • 279
  • 375
hawkeye
  • 4,819
  • 3
  • 24
  • 35
  • 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 – Richard Tingle Jan 01 '17 at 14:34
  • If you are studing the problems involving the use of microservices the Fowler article is a must read.http://www.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 04 '17 at 08:36
  • 2
    That commentator is short-sighted. Run time problem => prod issues => unhappy users => lost money. – Philipp Jan 04 '17 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. – Jörg W Mittag Sep 05 '18 at 17:23

5 Answers5

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.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
Paul Stovell
  • 1,689
  • 1
  • 9
  • 14
  • 69
    +1. This is much better as a Stack Exchange answer than as a tweet. :-) – ruakh Jan 01 '17 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 02 '17 at 09: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 02 '17 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 02 '17 at 17:45
  • 18
    Very nice answer. Thanks for confirming my opinion of Twitter as utterly useless for anything except stirring people up. – Robert Harvey Jan 02 '17 at 18:26
  • 1
    "Monolithic" vs microservices seems like a false dilemma. – Sam Jan 02 '17 at 22:26
  • it's just once again "here something new, let's rush it and make it our new silver bullet since the last one was crap". – Walfrat Jan 03 '17 at 08:23
  • @Walfrat many of those silver bullets are actually *better* than what came before, just not enough to be silver bullets... – Jared Smith Jan 03 '17 at 12:11
  • `inherit` -> `inherent` fits the context better – Brian Jan 03 '17 at 20:39
  • 1
    Plenty of "good teams" use microservices, and plenty of "bad teams" use monolithic architectures. I think the strawman being fought here is that organizational dysfunction is the ONLY reason teams choose microservices. The risks are the same compile-time or runtime. Bugs exist in code that compiles, too. Microservices enable faster deployments of code, even within high-functioning teams. As systems grow more complex it is impossible for a single developer (even Paul) to wrangle them all without delegating control. Something relatively contained like Octopus Deploy, perhaps. – Peter J Jan 04 '17 at 15:24
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.

amon
  • 132,749
  • 27
  • 279
  • 375
  • 2
    Is this your personal viewpoint, or are you confident this is what the commentator in question meant with the quip? – JacquesB Jan 01 '17 at 13:19
  • 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 01 '17 at 13:31
  • 1
    microservices lets you deploy updated versions of each component independently from each other. A company like Uber can deploy a new versions of a microservice just in one town, then role it out once it is proven, anther team can be live testing their new versions in a different time. – Ian Jan 01 '17 at 19:34
  • 10
    "monolith that is cleanly divided into components" - what the hell does that mean? –  Jan 01 '17 at 22:43
  • 10
    And not to speak of versioning of interfaces (interfaces changing over time). – Peter Mortensen Jan 01 '17 at 23:17
  • 3
    @PeterMortensen Amen! Although there are benefits to decoupling the components -- particularly if they naturally can (but don't *have to*) run on multiple machines -- keeping the various consumers up to date with any API changes is a First Class PITA. – Peter Rowell Jan 01 '17 at 23:26
  • 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 01 '17 at 23:55
  • 6
    Einstein said "Everything should be made as simple as possible, but no simpler." And here we see what he means. – Sam Jan 02 '17 at 22:19
  • Sort of relevant XKCD: https://xkcd.com/927/ – David says Reinstate Monica Jan 03 '17 at 15:49
  • 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 03 '17 at 17:38
  • 1
    Are you not doing any integration testing? No CI/CD pipeline? I've got multiple sources telling me microservices will fail without that tooling, and they're ADVOCATES of (or, at least not highly critical of) the architecture. – Rob Crawford Jan 03 '17 at 19:57
  • 4
    I would suggest "If you are unable to design a monolith that is cleanly divided into components, you will be *even less able* to design a microservice system" – user469104 Jan 03 '17 at 22:30
  • 2
    There are two issues with this answer. The first is that it ignores that it's much easier to be strict about isolation and decoupling in a microservices context, because it's *forced* by the architecture. The second is that it claims that 'OOP has been teaching [splitting up code into components] for decades', but that's only half true: the OOP code I've seen tends to be a mess of classes all interacting with each other, all with mutable state, etc. If anything, it's the functional programming guys that have been teaching decoupling and isolation, as pure functions are inherently isolated. – Miles Rout Jan 03 '17 at 23:38
  • *"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"*--only if you're developing with siloed waterfalls instead of iteratively. – chrylis -cautiouslyoptimistic- Jan 03 '17 at 23:46
  • 1
    @chrylis When developing iteratively, you still have points where you integrate components, often at the end of each iteration. – user253751 Jan 04 '17 at 02:49
  • 1
    For interface type mismatches; the normal approach is to (e.g.) have a header file that defines the interface and ensures that you get static checking at compile time. It doesn't matter much if the "thing on the other side of the interface" is a micro-service or a statically linked library (or a dynamically linked library that only contains code to communicate with a micro-service, or...). – Brendan Jan 04 '17 at 15:18
  • 1
    I'm not sure if it is technically microservices but I have had success with a building actor style services where the services exchange messages to communicate. Using ZeroMQ, I am able to compile the services into the application. The services are developed independently and can be compiled into their own executable for testing. The final monolith is just a container for the micro service threads. If I need to scale across machines, I use the executable version(s) and split the monolith across the machines where it makes sense. – JeffV Jan 30 '17 at 13:00
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.

Jörg W Mittag
  • 101,921
  • 24
  • 218
  • 318
  • I don't follow how low code quality is *caused* by higher level management - they aren't writing the code, the developers are. – Michael Jan 01 '17 at 16:48
  • 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 01 '17 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 … – Jörg W Mittag Jan 01 '17 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*. – Jörg W Mittag Jan 01 '17 at 17:22
  • @wjl Ah ok. I was thinking of it in the context of the length of the feedback loop.. making it go through management seems to decrease quality because instead of getting immediate feedback (e.g. compiler error) it gets deployed and the developer doesn't find out until later when they have probably task switched. This does not need to have anything to do with incompetence and everything to do with correcting minor mistakes that inevitably happen - the closer these are fixed to when they are made, the better. – Michael Jan 01 '17 at 19:57
  • 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. – Stijn de Witt Jan 02 '17 at 21:48
  • @StijndeWitt No but atleast the problems arent buried in the system and blame goes to the right source. – joojaa Jan 03 '17 at 15:29
  • There used to be a saying: "The Buck Stops Here" but apparently not anymore? –  Jan 03 '17 at 18:38
  • 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 03 '17 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.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
  • 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 01 '17 at 12:39
  • 1
    @JacquesB OTOH, I can think of exactly zero dynamically typed compiled languages. – user253751 Jan 01 '17 at 13:39
  • @immibis: Well JavaScript and Python comes to mind. But in any case I don't really see the relevance - does monolithic applications have to be compiled? – JacquesB Jan 01 '17 at 13:43
  • 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 01 '17 at 13:45
  • @immibis: Haskell and RPython are compiled to machine language and from the point of programmer they are more or less dynamically typed (strictly speaking they use type inference so there's no type selection overhead at runtime, but that's really just implementation detail). Also, regular Python implementation, CPython is compiled to Python VM bytecode, producing .pyc/.pyo files; which is no different than Java. – Lie Ryan Jan 01 '17 at 15:58
  • 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. – Jörg W Mittag Jan 01 '17 at 17:26
  • 1
    Some Scheme implementations and many CommonLisp implementations are statically AOT compiled. OTOH, there are interpreters for C and C++. – Jörg W Mittag Jan 01 '17 at 17:27
  • 12
    @LieRyan You are seriously confused if you think type inference is the same as dynamically typed and/or that *Haskell* is dynamically typed. – Derek Elkins left SE Jan 01 '17 at 20:36
  • 1
    @LieRyan Haskell is not in any way dynamically typed. .pyc/.pyo files are internal interpreter structures. – user253751 Jan 02 '17 at 00:44
  • @immibis: Clojure. –  Jan 02 '17 at 20:20
  • Common Lisp is dynamically typed, and compiled. (Although you could run it through an interpreter, but that's true for C too. Then again, to be fair, is C *really* typed? ;) ) As for statically typed microservices, that sounds like something only SOAP-fans (either one of them), could dream up. – Haakon Løtveit Jan 03 '17 at 13:16
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.

bernie
  • 109
  • 5