[HN Gopher] Microservices Considered Harmful (2019)
       ___________________________________________________________________
        
       Microservices Considered Harmful (2019)
        
       Author : maattdd
       Score  : 91 points
       Date   : 2020-06-07 17:51 UTC (5 hours ago)
        
 (HTM) web link (blog.matthieud.me)
 (TXT) w3m dump (blog.matthieud.me)
        
       | SiNiquity wrote:
       | In my experience, the benefits of microservices are primarily
       | better delineated responsibilities and narrower scope, and
       | secondary benefits tend to fall out from these. There are
       | downsides, but the "harmful" effects do not reflect my
       | experience. I fully grant more things on a network invite lower
       | availability / higher latency, but I contend that you already
       | need to handle these issues. Microservices do not tend to grossly
       | exacerbate the problem (in my experience anyway).
       | 
       | The other callout is clean APIs over a network can just be clean
       | APIs internally. This is true in theory but hardly in practice
       | from what I've seen. Microservices tend to create boundaries that
       | are more strictly enforced. The code, data and resources are
       | inaccessible except through what is exposed through public APIs.
       | There is real friction to exposing additional data or models from
       | one service and then consuming it in another service, even if
       | both services are owned by the same team (and moreso if a
       | different team is involved). At least in my experience, spaghetti
       | was still primarily the domain of the internal code rather than
       | the service APIs.
       | 
       | There's also a number of benefits as far as non-technical
       | management of microservices. Knowledge transfer is easier since
       | again, the scope is narrower and the service does less. This is a
       | great benefit as people rotate in and out of the team, and also
       | simplifies shifting the service to another team if it becomes
       | clear the service better aligns with another team's
       | responsibilities.
        
       | jayd16 wrote:
       | Hammer considered harmful. Cannot secure screws, says blog.
        
         | HideousKojima wrote:
         | Hammers work great for driving screws if you have an impact
         | driver (the hand tool kind)
        
       | djsumdog wrote:
       | The author is totally right about the HTTP layer/networking
       | stuff. I don't think you have to re-implement SQL transactions,
       | but you do need a backing store that allows acknowledging a
       | message has been processed and not down-sides to processing the
       | same thing twice (idempotent).
       | 
       | I did a post about microservices as I've seen them, and I see the
       | more as software evolution matching that of our own biological
       | and social evolution:
       | 
       | https://battlepenguin.com/tech/microservices-and-biological-...
       | 
       | Like our own immune system, the thousands of moving parts have
       | somehow evolved to fight infections and keep us alive, but it's
       | easy to not be able to understand how any of it really works
       | together.
        
       | staticassertion wrote:
       | > However, your codebase has now to deal with network and
       | multiple processes.
       | 
       | Here's the thing I see repeatedly called out as a negative, but
       | it's a positive!
       | 
       | Processes and networks are amazing abstractions. They force you
       | to not share memory on a single system, they encourage you to
       | focus on how you communicate, they give you scale and failure
       | isolation, for force you to handle the fact that a called
       | subroutine might fail because it's across a network.
       | 
       | > f your codebase has failed to achieve modularity with tools
       | such as functions and packages, it will not magically succeed by
       | adding network layers and binary boundaries inside it
       | 
       | Functions allow shared state, they don't isolate errors.
       | Processes over networks do. That's a massive difference.
       | 
       | If you read up on the fundamental papers regarding software
       | reliability this is something that's brought up ad nauseum.
       | 
       | > (this might be the reason why the video game industry is still
       | safe from this whole microservice trend).
       | 
       | Performance is more complex than this. For a video game system
       | latency might be the dominating criteria. For a data processing
       | service it might be throughput, or the ability to scale up and
       | down. For many, microservices have the performance
       | characteristics that they need, because many tasks are not
       | latency sensitive, or the latency sensitive part can be handled
       | separately.
       | 
       | > would argue that by having to anticipate the traffic for each
       | microservice specifically, we will face more problem because one
       | part of the app can't compensate for another one.
       | 
       | I would argue that if you're manually scaling things then you're
       | doing it wrong. Your whole system should grow and shrink has
       | needed.
        
         | [deleted]
        
         | mpfundstein wrote:
         | > Processes and networks are amazing abstractions. They force
         | you to not share memory on a single system, they encourage you
         | to focus on how you communicate, they give you scale and
         | failure isolation, for force you to handle the fact that a
         | called subroutine might fail because it's across a network.
         | 
         | Stop on! Its so much easier to enforce separation of concern if
         | there is an actual physical barrier. Its just to easy to just
         | slip bad decision through peer review.
         | 
         | So I totally agree
        
           | mattupstate wrote:
           | Stop off! Drop a bunch "microservices" into the same network
           | without any access control and you don't have a physical
           | barrier at all! In fact, it becomes even harder to have a
           | clue as to what's interfacing with what unless you can
           | observe your inter process traffic.
        
             | staticassertion wrote:
             | This is a completely unrelated issue. Microservices have
             | nothing to do with access control. If anything, they should
             | lend themselves to more fine grained control, but again,
             | microservice architecture says nothing about it.
        
             | yellowapple wrote:
             | > without any access control
             | 
             | The point, I reckon, is that you should be implementing
             | access control.
        
         | mic47 wrote:
         | > Functions allow shared state, they don't isolate errors.
         | 
         | So why not use Haskell (or other pure language)? It's pure, so
         | functions don't share state. And you don't have to replace
         | function call with network call.
        
           | staticassertion wrote:
           | You'll never achieve the level of operational stability of an
           | air gap that you would without a strictly in process system.
           | 
           | Shared state is part of it. Isolation of failure is another.
           | Your Haskell code can still blow up.
           | 
           | Immutability makes that way easier to recover from, but it's
           | just one part.
           | 
           | Of course, microservices are much more than processes over a
           | network, they're a discipline. And I think one can go much
           | further than microservices as well - microservice
           | architecture doesn't tell you _how_ processes should
           | communicate, it 's more focused on how they're split up, and
           | leaves the protocol to you. Good protocol design is critical.
        
         | amelius wrote:
         | > They force you to not share memory on a single system, they
         | encourage you to focus on how you communicate, they give you
         | scale and failure isolation, for force you to handle the fact
         | that a called subroutine might fail because it's across a
         | network.
         | 
         | The problem: distributed systems are hard to get right. Better
         | stay away from them unless you really need them, AND you have
         | the time/resources to implement them correctly. The benefits of
         | microservices are a bad excuse, most of the time.
        
         | mixedCase wrote:
         | > for force you to handle the fact that a called subroutine
         | might fail because it's across a network.
         | 
         | That just adds one failure mode to the list of failure modes
         | people ignore due to the happy-path development that languages
         | with "unchecked exceptions as default error handling"
         | encourage.
         | 
         | > Functions allow shared state, they don't isolate errors.
         | Processes over networks do. That's a massive difference.
         | 
         | Except not, because "just dump that on a database/kv-store" is
         | an all-too-common workaround chosen as an easy way out. This
         | problem is instead tackled by things such as functionally pure
         | languages such as Haskell and Rust's borrow checker, and only
         | up to a certain degree at which point it's still back into the
         | hands of the programmer's experience; though they do help a
         | ton.
        
           | staticassertion wrote:
           | > That just adds one failure mode to the list of failure
           | modes people ignore due to the happy-path development that
           | languages with "unchecked exceptions as default error
           | handling" encourage.
           | 
           | There are only two meaningful failure modes - persistent and
           | transient. So adding another transient failure (network
           | partition) is not extra work to handle.
           | 
           | > Except not, because "just dump that on a database/kv-store"
           | is an all-too-common workaround chosen as an easy way out.
           | 
           | Just to be clear, microservices are not just separate
           | binaries on a network. If you're not following the actual
           | patterns of microservice architecture... you're just
           | complaining about something else.
        
           | yellowapple wrote:
           | > Except not, because "just dump that on a database/kv-store"
           | is an all-too-common workaround chosen as an easy way out.
           | 
           | Then maybe we should be criticizing that instead? Like,
           | that'd still happen with Haskell or Rust (or, in my
           | experience, Erlang, with that KV store specifically being
           | ETS). Seems like that's the thing that needs addressed.
        
         | twic wrote:
         | > If you read up on the fundamental papers regarding software
         | reliability this is something that's brought up ad nauseum.
         | 
         | I don't believe there are any papers that show that adding
         | network hops to an application makes it more reliable. I would
         | be extremely interested in any references you could provide.
        
           | staticassertion wrote:
           | Not the network bit, the separation of state and the process
           | abstraction.
           | 
           | https://www.hpl.hp.com/techreports/tandem/TR-85.7.pdf
           | 
           | Here's one paper that discusses building reliable systems
           | from two abstractions - the process and transaction.
        
       | Gollapalli wrote:
       | Microservices have some inherent advantages, mainly that you can
       | manage, modify and deploy one service at a time, without taking
       | down/redeploying the rest of your application(s). This is
       | arguably the big thing that is missing from monoliths. It's hard
       | to only change a single API endpoint in a monolith, but easier to
       | do a change across the entire monolith, when you have to change
       | something about how the whole system works. The best compromise
       | that I've come up with would be to have something that can keep
       | your entire app in one place, but allow individual portions of it
       | to be hot-swapped in the running application, and is built to be
       | run in a distributed, horizontally scalable fashion, In addition,
       | there's a lot to be said for the old way of putting business
       | logic in stored procedures, despite the poor abstraction
       | capabilities of SQL, relative to something like lisp, but with
       | modern distributed databases, we can conceivably run code in
       | stored procedures written in something like Clojure, keeping code
       | close to the database, or rather, data close to the code,
       | allowing hot-swapping, modification, introspection, replay of
       | events, and all other manner of things, all while managing the
       | whole thing like a monolith, with a single application,
       | configuration, etc. to deploy, and a more manageable and obvious
       | attack surface to secure.
       | 
       | This is my solution, called Dataworks, if anyone's interested:
       | https://github.com/acgollapalli/dataworks#business-case
       | 
       | (Some of those things like introspection and replay-of-events are
       | in the road map, but the core aspects of hotswapping and
       | modification of code-in-db work.)
        
       | ts0000 wrote:
       | While I agree with the notion of treating microservices with
       | caution, I found the article a bit too shallow, barely supporting
       | the claim. Especially the second "fallacy" reads like a draft and
       | it overall ends abruptly.
        
       | trentdk wrote:
       | A major benefit to microservices (over monoliths) that I haven't
       | seen mentioned yet is testability. I find it hard, or improbable
       | to achieve a healthy Pyramid of Tests on a large monolith.
       | 
       | For example: a high level, black box test of a service endpoint
       | requires mocking external dependencies like other services,
       | queues, and data stores. With a large monolith, a single process
       | might touch a staggering number of the aforementioned
       | dependencies, whereas something constrained to be smaller in
       | scope (a microservice) will have a manageable number.
       | 
       | I enjoy writing integration and API tests of a microservice. The
       | ones that we manage have amazing coverage, and any refactor on
       | the inside can be made with confidence.
       | 
       | Our monoliths tend to only support unit tests. Automated end-to-
       | end tests exist, but due to the number of dependencies these
       | things rely on, they're executed in a "live" environment, which
       | makes them hardly deterministic.
       | 
       | Microservices allow for a healthy Pyramid of Tests.
        
         | jasonhansel wrote:
         | This is true for moderately-sized microservices. If your
         | microservices are _too_ small, though, it 's essentially
         | impossible to write integration tests of the overall system as
         | a whole--any such test would need to spin up N different
         | dependencies.
        
           | Bnshsysjab wrote:
           | So a solution has now caused problems which were solved 30
           | years ago
        
         | BurningFrog wrote:
         | Microservice testing come with version combination hell.
         | 
         | If you have 10 microservices, each of which can be on one of
         | two versions, that's 1024 combinations. How do you test that?
        
           | pojzon wrote:
           | Im yet to see a system that consists of other versions of
           | code than "new" and "current". You test against changes only,
           | what you described is some mess in deployed versions /
           | versions management.
        
             | BurningFrog wrote:
             | How is this different from what I'm describing?
             | 
             | "New" and "current" _are_ two different versions.
        
         | twic wrote:
         | This is absolutely a fallacy. If you're testing a microservice
         | and stubbing the other microservices, you aren't doing the
         | equivalent of the high-level test on the monolith. You're doing
         | something like a macro-unit test of the monolith with internal
         | services stubbed.
        
           | mac-chaffee wrote:
           | I think there's a tendency to believe that a microservice
           | written by someone else can be replaced with a stub that just
           | validates JSON or something.
           | 
           | But in my experience, that thinking leads to bugs where the
           | JSON was correct, but it still triggers an error when you run
           | real business logic on it.
           | 
           | It's an easy trap to fall into because that microservice
           | exists to abstract away that business logic, but you can't
           | just pretend it doesn't exist when it comes to testing.
           | 
           | So stubs may be good for unit tests, but only if there are
           | integration tests to match.
        
             | isbvhodnvemrwvn wrote:
             | It's also useful if the team providing the service can
             | provide a fake or a stub with interesting pre-programmed
             | scenarios, this reduces the number of false assumptions
             | someone can make, is sort of a living documentation
             | (assuming people update their fakes). Something like
             | contract testing (Pact etc) can also be useful, although I
             | haven't seen it being used in practice yet.
        
         | mpweiher wrote:
         | > I find it hard, or improbable to achieve a healthy Pyramid of
         | Tests on a large monolith
         | 
         | I'd venture to say that this is a strong indication that _You
         | 're Holding it Wrong_(tm)
         | 
         | > a high level, black box test of a service endpoint
         | 
         | Then maybe don't do these kinds of high-level black box tests?
         | 
         | Because...
         | 
         | > requires mocking external dependencies
         | 
         | ...if you're stubbing out everything, then it's _not_ actually
         | a high-level, black-box test. So no use pretending it is and
         | having all these disadvantages.
         | 
         | Instead, use hexagonal architecture to make your code usable
         | and testable without those external connections and only add
         | them to a well-tested core.
         | 
         | See: _Why I don 't Mock_ (2014)
         | https://blog.metaobject.com/2014/05/why-i-don-mock.html
         | 
         | Discussed at the time:
         | https://news.ycombinator.com/item?id=7809402
        
       | avip wrote:
       | I just wish we had industry standards. If this and such is your
       | prob., this and that architecture is the simplest that works.
       | 
       | Structure engineers have such books. They need to build something
       | speced to hold X tonnes here are the possibilities outlined in
       | simple drawings.
       | 
       | I need to bump my head on any problem I'm facing and I live in
       | constant doubt that I took the wrong technical decisions.
        
       | bhntr3 wrote:
       | Microservices are the actor model (erlang or akka) except they
       | require lots of devops work, being on call for x services every
       | night, and a container management system like kubernetes to be
       | manageable.
       | 
       | Actors are a simple solution to the same problems microservices
       | solve and have existed since the 1970s. Actor implementations
       | address the problem foundationally by making hot deployment,
       | fault tolerance, message passing, and scaling fundamental to both
       | the language and VM. This is the layer at which the problem
       | should be solved but it rules out a lot of languages or tools we
       | are used to.
       | 
       | So, in my opinion, microservices are a symptom of an abusive
       | relationship with languages and tools that don't love us, grow
       | with us or care about what we care about.
       | 
       | But I also think they're pretty much the same thing as EJBs which
       | makes Kubernetes Google JBoss.
        
       | cameronbrown wrote:
       | Microservices were never about code architecture, they were an
       | organisational pattern to enable teams to own different services.
       | Most "microservices" don't actually look micro to those
       | implementing them, because it's really just "a lot of services".
       | 
       | For my personal projects, I just have a frontend service (HTTP
       | server) and a backend service (API server). Anything more is
       | overkill.
        
         | benhoyt wrote:
         | Agreed. Or as I've heard it said, "microservices solve a people
         | problem, not a technical one". This is certainly how they were
         | pushed at my current workplace -- it was all about "two-pizza
         | teams being able to develop and deploy independently".
         | 
         | Out of interest, what does the "frontend service" do in your
         | setup? For my personal projects I generally just go for a
         | single server/service for simplicity.
        
           | cameronbrown wrote:
           | My frontend services handles all user requests (HTML
           | templates, i18n, analytics, authentication). Backend is
           | exclusively focused on business logic, interacting with DB,
           | cron jobs, etc... My projects grew into this naturally, and
           | it was monolith first.
        
         | bjt wrote:
         | I came here to make a similar point. I see two big benefits to
         | microservices, neither of which is spoken to by the article:
         | 
         | 1. Using small-ish (I hate the word "micro"), domain-bounded
         | services leads engineers to think more carefully about their
         | boundaries, abstractions, and interfaces than when you're in a
         | monolith. It reduces the temptation to cheat there.
         | 
         | 2. Conway's law is real. If you don't think very deliberately
         | about your domain boundaries as you code, then you'll end up
         | with service boundaries that reflect your org structure. This
         | creates a lot of pain when the business needs to grow or pivot.
         | Smaller, domain-bounded services give you more flexibility to
         | evolve your team structure as your business grows and changes,
         | without needing to rewrite the world.
         | 
         | I'm a big fan of the "Monolith First" approach described by
         | Martin Fowler. Start with the monolith while you're small.
         | Carve off pieces into separate services as you grow and need to
         | divide responsibilities.
         | 
         | A multi service architecture works best if you think about each
         | service as a component in a domain-driven or "Clean
         | Architecture" model. Each service should live either in the
         | outer ring where you interface with the outside world or the
         | inner ring where you do business logic. Avoid the temptation to
         | have services that span both. And dependencies should only
         | point inward.
         | 
         | Carving pieces off a monolith is easier if the monolith is
         | built along Clean Architecture lines as well, but in my
         | experience, the full stack frameworks that people reach for
         | when starting out (e.g Rails, Django) don't lead you down a
         | cleanly de-couple-able path.
         | 
         | https://en.wikipedia.org/wiki/Conway%27s_law
         | 
         | https://www.thoughtworks.com/radar/techniques/inverse-conway...
         | 
         | https://martinfowler.com/bliki/MonolithFirst.html
         | 
         | https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-a...
        
         | tomlagier wrote:
         | I think that pattern scales really well up to a medium-sized
         | startup.
         | 
         | I stick those two (webserver/static content and API) plus a
         | database in a docker-compose file, and put all three plus a
         | frontend in a single repo. That feels like the sweet spot of
         | "separate but integrated" for my work.
        
       | ceronman wrote:
       | I once read a quote that was something like "You are only an
       | expert in a given technology when you know when _not_ to use it
       | ". Unfortunately I forgot the exact quote and the author. (If
       | anyone knows please let me know).
       | 
       | This is such a nice quote that speaks a lot about what it means
       | to be an experienced (senior) software engineer. Our field is
       | such a dynamic one! New tools and techniques appear all the time.
       | 
       | It's easy to fall into the trap of thinking that newer tools are
       | better. I think this is because in some areas of tech this is
       | almost always true (e.g. hardware). But in software, new tools
       | are techniques are rarely fully better, instead they just provide
       | a different set of trade offs. Progress doesn't follow a linear
       | pattern, it's more like a jagged line slowly trending upwards.
       | 
       | We think we are experienced because we know how to use new tools,
       | but in reality we are only more experienced when we understand
       | the trade offs and learn when the tools are really useful and
       | when they are not.
       | 
       | A senior engineer knows when not to use micro services, when not
       | to use SQL, when not to use static typing, when not to use React,
       | when not to use Kubernetes, etc.
       | 
       | Junior engineers don't know these trade offs, they end up using
       | sophisticated hammers for their screws. It doesn't mean that
       | those hammers are bad or useless, they were just misused.
        
       | z3t4 wrote:
       | Take away the word micro from micro services. Its just a
       | buzzword. Now you have just services. You can have just one
       | service that handles email, chat, payroll, website - or you can
       | break them up into independent services. Ask yourself: Does it
       | make sense to have two different services to handle x and y. Just
       | don't break something up because of some buzzword mantra. Maybe
       | the public website is the bottleneck in your monolith, then it
       | might be a good idea to put it on its own server and scaling
       | strategy so that it doesn't bog down the other parts of the
       | system.
        
         | eldelshell wrote:
         | Yeah, something in between a monolith and microservices, and
         | I'm going to name it: services architecture.
         | 
         | Hmmm... I think I can do better: Service Oriented
         | Architecture... Yeah I like this name. SOA.
         | 
         | Are you telling me I just invented something that's 30 years
         | old? Bollocks!
        
           | Bnshsysjab wrote:
           | Can you articulate SOA without using buzzwords?
           | 
           | I assume it's concepts like a dedicated TLS terminator,
           | Single Sign on, centralised logging, etc?
        
         | ismayilzadan wrote:
         | Agreed. I was going to add my own separate comment but noticed
         | yours. I think the main issue is, most companies nowadays end
         | up creating "nano" services. A normal "service" should be built
         | and then if functionality/team gets too big, then you break it
         | down into another 2-3 smaller services. Again, service code
         | already should have been written in a clean, modular code style
         | so it can be broken down easily too without rearchitecting
         | whole stack.
        
           | ShellfishMeme wrote:
           | But is it really true that so many companies create too small
           | services? I admit I haven't seen too many architectures from
           | the inside but from my experience the problem is usually the
           | opposite: adding more and more things to a monolith that
           | already has serious complexity and scalability issues because
           | it's the convenient place and is faster to develop. Most of
           | the times I heard about the nano services problem was from
           | articles warning of using services and encouraging monoliths
           | instead.
        
       | Discombulator wrote:
       | Without going into detail on the actual debate, I just want to
       | make a meta point here: If you are writing an article and the
       | following
       | 
       | > [All] technical challenges [...] will not be magically solved
       | by using microservices
       | 
       | Is the key statement of your article, then you should really
       | consider adding a lot of nuance or not publishing it at all.
        
       | vyrotek wrote:
       | _Spaghetti over HTTP_
       | 
       | That must make meatballs the DBs and parmesan the JS frameworks.
        
       | yellowapple wrote:
       | > Network failure (or configuration error) is a reality. The
       | probability of having one part of your software unreachable is
       | infinitely bigger now.
       | 
       | Network partitions are indeed a problem for distributed software
       | in general. By the time microservices are worthwhile, however,
       | the application likely already necessitates a distributed design.
       | 
       | > Remember your nice local debugger with breakpoints and
       | variables? Forget it, you are back to printf-style debugging.
       | 
       | ...why? What's stopping you from using a debugger? A microservice
       | v. a monolith should make zero difference here.
       | 
       | At worst, you might have to open up multiple debuggers if you're
       | debugging multiple services. Big whoop.
       | 
       | > SQL transaction ? You have to reimplement it yourself.
       | 
       | ...why? What's stopping you from pulling it from a library of
       | such transactions?
       | 
       | I don't even really think this is a "problem" per se. Yeah, might
       | be inconvenient for some long and complicated query, but that's
       | usually a good sign that you should turn that into a stored
       | procedure, or a view, or a service layer (so that other services
       | ain't pinging the database directly), or something else, since it
       | simply means bad "API" design (SQL being the "API" in this
       | context).
       | 
       | > Communication between your services is not handled by the
       | programming language anymore, you have to define and implement
       | your own calling convention
       | 
       | Which is arguably a good thing, since you're able to more readily
       | control that calling convention and tailor it to your specific
       | needs. It also gives ample opportunities for logging that
       | communication, which is a boon for troubleshooting/diagnostics
       | and for intrusion detection.
       | 
       | > Security (which service can call which service) is checked by
       | the programming language (with the private keyword if you use
       | classes as your encapsulation technique for example). This is way
       | harder with microservices: the original Monzo article shows that
       | pretty clearly.
       | 
       | The programming language can do little to nothing about security
       | if all the services are in the same process' memory / address
       | space; nothing stopping a malicious piece of code from completely
       | ignoring language-enforced encapsulation.
       | 
       | Microservices, if anything, help _considerably_ here, since they
       | force at least process-level (if not machine-level) isolation
       | that can 't so easily be bypassed. They're obviously not a silver
       | bullet, and there are other measures that should absolutely be
       | taken, but separation of concerns - and enforcing that separation
       | as strictly as possible - is indeed among the most critical of
       | those measures, and microservices happen to more or less bake
       | that separation of concerns into the design.
        
       | nindalf wrote:
       | I wish Dijkstra had named his article on the go to statement[1]
       | something else. It feels like every other author nowadays want to
       | use the sense of authority that the "considered harmful" gives
       | them. Like it's obvious and widely accepted that it's harmful,
       | and they're giving you an FYI.
       | 
       | Just name it "The downsides of microservices" and we'll know that
       | it's your personal opinion. This title might get you more clicks,
       | but it's a turn off for me.
       | 
       | [1] -
       | https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.p...
        
         | Someone wrote:
         | Don't blame Dijkstra for that.
         | https://en.m.wikipedia.org/wiki/Considered_harmful#History:
         | 
         |  _"The original title of the letter, as submitted to CACM, was
         | "A Case Against the Goto Statement", but CACM editor Niklaus
         | Wirth changed the title to "Go To Statement Considered
         | Harmful"."_
         | 
         | So, Dijkstra's choice for a title would be "A Case Against
         | Microservices".
        
         | lou1306 wrote:
         | (Actually it was Wirth that came up with the "Considered
         | Harmful" title. Dijkstra sent the paper as "A case against the
         | Goto statement" [1].)
         | 
         | I would go on a limb and say that CH-titles should be
         | themselves considered harmful. [2] Personally, my main issue
         | with them is that they invite (often unfavourable) comparisons
         | with EJD's paper.
         | 
         | [1]: https://en.wikipedia.org/wiki/Considered_harmful [2]:
         | https://meyerweb.com/eric/comment/chech.html
        
         | [deleted]
        
         | rectang wrote:
         | If you have enough karma, you can flag any article which uses
         | "Considered Harmful" in the title. That won't get rid of
         | clickbait in general, but maybe authors will choose a different
         | variety of clickbait.
        
         | rejschaap wrote:
         | It's great that people annotate biased articles with the words
         | "Considered Harmful"
        
         | deepsun wrote:
         | I've heard that arrogance is measured in nano-Dijkstras.
        
         | stephc_int13 wrote:
         | "Considered Harmful" has become a meme and a self-reference
         | with several levels of recursion.
         | 
         | I hated the obnoxious tone of the quote when I first heard it,
         | nowadays it makes me smile with a grin.
        
         | smcl wrote:
         | It's a bit overused, I'm almost certain I've seen an article
         | called _"Considered Harmful" Considered Harmful_
        
           | chrisco255 wrote:
           | Ah, yes, the recursive Considered Harmful. This article was
           | quickly followed up by the rebuke "'Considered Harmful'
           | Considered Harmful" Considered Harmful. Shortly thereafter,
           | the entire blogosphere had a stack overflow error and nearly
           | took the entire internet offline along with it. Recursive
           | Considered Harmful Considered Harmful.
        
         | phlakaton wrote:
         | I never quite understood the objection to "considered harmful."
         | To me the very wording of the phrase is a jest; it's said with
         | tongue firmly planted in cheek, even if what follows is quite
         | serious, and it fully and effectively declares its intention to
         | go poke some sacred cow in the eye. I never read it as
         | overbearing or judgmental. I love it!
        
           | sildur wrote:
           | It feels pompous to me.
        
       | stillbourne wrote:
       | Microservices are middleware. That's they way I treat them
       | anyway. I build them as the glue between the backend and
       | frontend. They handle things like authentication, business logic,
       | data aggregation, caching, persistence, and generally act as an
       | api gateway. I really only ever use microservices to handle
       | crosscutting concerns that are not directly implemented by the
       | backend but have a frontend requirement. The only way that is
       | harmful is if you write bad code. Bad code is always harmful.
        
         | Closi wrote:
         | You aren't really implementing a microservices architecture in
         | that case though.
         | 
         | The idea of microservices is that they are self-contained, not
         | just middleware to a monolithic backend.
        
           | stillbourne wrote:
           | That statement goes against everything I have learned about
           | SOA and microservices.
           | 
           | https://apifriends.com/api-management/microservices-soa/
        
             | Closi wrote:
             | The central premise of microservices architecture is that
             | the services manage their own data.
             | 
             | If you have a shared data store then you are not really
             | implementing microservices.
             | 
             | https://docs.microsoft.com/en-
             | us/azure/architecture/microser...
             | 
             | In fact, the linked article by Martin Fowler pretty much
             | describes it as the opposite of what you are describing:
             | 
             | https://martinfowler.com/articles/microservices.html
        
       | plandis wrote:
       | > A recent blog post by neobank Monzo explains that they have
       | reached the crazy amount of 1500 microservices (a ratio of ~10
       | microservices per engineer)
       | 
       | That's wild. Microservices are mostly beneficial organizationally
       | -- a small team can own a service and be able to communicate with
       | the services of other small teams.
       | 
       | If anything I think a 10:1 software engineers:services is
       | probably not far off from the ideal.
        
         | djsumdog wrote:
         | At a goto; talk, an Uber engineer said they had so many
         | microservices it was impossible to really count how many they
         | had:
         | 
         | https://www.youtube.com/watch?v=kb-m2fasdDY
        
           | hrpnk wrote:
           | That really depends how you count them and how you manage the
           | entire application landscape. For audit, compliance,
           | security, and risk management purposes you really need to
           | know what the service is doing and what criticality level it
           | is.
           | 
           | Surely, you can make the creation of services _really_ easy -
           | so easy that it 's not even viable to define meaningful
           | business names for the services, thus creating an
           | unmaintainable mess. But still, having an application
           | registry or automation that crawls the cloud resources for
           | services can be done afterwards without significantly
           | impacting the speed of creating new services.
        
         | twic wrote:
         | If you have ten people working full-time on it, it is not a
         | microservice, it is just a service.
         | 
         | I think the discussion about microservices has suffered more
         | than anyone realises from a lack of shared understanding about
         | what a microservice actually is.
        
           | pojzon wrote:
           | What in case when that ,,service" is actually a thousend of
           | ,,microservice instances" thats communicating with other
           | ,,services" via some ,,api gateways"?
           | 
           | And the teams managing those ,,services" do full DevSecOps?
           | 10 people working on such component is actually pretty decent
           | team size for that task...
        
         | michaelbuckbee wrote:
         | When I hear things like that all I can think is that I have a
         | wildly different idea of what a "service" is that it can be
         | broken down to such a small chunk of functionality.
         | 
         | Are there examples of the size of these individual services?
         | What are they doing?
        
         | axlee wrote:
         | > That's wild. Microservices are mostly beneficial
         | organizationally -- a small team can own a service and be able
         | to communicate with the services of other small teams.
         | 
         | And a cross-concern fix that a dev used to be able to apply by
         | himself in a day, now has to go through 5 teams, 5 programming
         | languages, 5 kanban boards and 5 QA runs to reach production. I
         | never understood the appeal of teams "owning" services. In my
         | dream world, every engineer can and should be allowed to
         | intervene in as many layers/slices of the code as his mental
         | capacity and understanding allows. Artificial - and sometimes
         | bureaucratic - boundaries are hurtful.
         | 
         | To me, it's the result of mid-to-senior software engineers not
         | being ready to let go of their little turfs as the company
         | grows, so they build an organizational wall around their code
         | and call it a service. It has nothing to do with computer
         | science or good engineering. It is pure Conway's law.
        
           | hrpnk wrote:
           | In my experience, ownership of services is usually defined to
           | ensure that in the engineering organization it's clear who
           | will react as the first responder when there are security
           | patches, production incidents to deal with and also when
           | there are questions about the service's inner workings. It's
           | especially required when the documentation of the services is
           | sparse which is likely to happen when the change rate in the
           | team is high.
           | 
           | In more mature engineering organizations, you would define a
           | set of maintainers for the service, who will define the
           | contribution mechanisms and guidelines, so that anyone can
           | make changes to the code. This is further enabled by common
           | patterns and service structures, especially when there is a
           | template to follow. Strict assumed "ownership" creates anti-
           | patterns where each team will define their favourite tech
           | stack or set of libraries making it difficult for others to
           | contribute and decreasing the possible leverage effects in
           | the team.
        
             | axlee wrote:
             | Maybe it is simply a terminology issue, but what you
             | describe, I would call it responsibility rather than
             | ownership. Ownership implies strong exclusivity. Agree with
             | your post otherwise.
        
           | cassianoleal wrote:
           | > And a cross-concern fix that a dev used to be able to apply
           | by himself in a day, now has to go through 5 teams, 5
           | programming languages, 5 kanban boards and 5 QA runs to reach
           | production.
           | 
           | If you ever find yourself in that situation, rest assured
           | that something went wrong way before the decision to use
           | microservices was made.
           | 
           | If your systems are that tightly coupled you'll have problems
           | regardless of architecture.
        
         | snowoutside wrote:
         | I think 10:1 is a bit much. If services are well-scoped, 3
         | engineers/service can be an effective ratio.
        
       | sascha_sl wrote:
       | microservices are useful, but not for the reasons listed here (or
       | the reasons often assumed)
       | 
       | personally, i'm more a fan of "realm of responsibility scoped
       | services" to decouple technologies/datastores of parts of a
       | system that do not interact by design (for instance, your user
       | account / credentials handling from literally anything else), and
       | then use a system like kafka (with producer-owned format) to have
       | a common data bus that can tolerate services that process data
       | asyncronously (or even things that keep users in the typical
       | "refresh loop") dying for a bit.
        
       | anm89 wrote:
       | Came here to complain about "considered harmful" click bait and
       | was happily surprised to find everyone else already feels the
       | same.
        
       | marcinzm wrote:
       | >If your codebase has failed to achieve modularity with tools
       | such as functions and packages, it will not magically succeed by
       | adding network layers and binary boundaries inside it
       | 
       | This is assuming you're converting an existing non-modular
       | monolithic service to micro services. If you're starting from
       | scratch or converting a modular monolithic service then this
       | point is moot. It says nothing about the advantages or
       | disadvantages of maintaining a modular code base with monoliths
       | or microservices which is what people are actually talking about.
        
         | mic47 wrote:
         | If you are starting from scratch (again), you can make good
         | monolith too, since you already know a lot about the problem
         | you are solving.
        
           | marcinzm wrote:
           | The issue generally isn't just creating something clean but
           | rather it's maintaining something clean. Something that will
           | be owned not by you but by multiple teams whose members
           | change over the course of years.
           | 
           | On a side note, I've found that creating something again
           | usually leads to messes as you try to fix all the issues in
           | the original which just creates new issues.
        
           | bdcravens wrote:
           | This seems to always be the case when two alternatives are
           | discussed on HN. The new and shiny is muddled with the new
           | design, so it's hard to tease out where the improvement came
           | from, and in most cases, the new design is possible in the
           | old and trusted.
        
         | marcosdumay wrote:
         | The point stands. If you can create good interfaces over a
         | network, you can create good interfaces over function calls
         | too.
        
           | marcinzm wrote:
           | The difference you miss is that the former discourages bad
           | interfaces and the latter does not. There is no "you" in most
           | businesses. There's dozens of people who changes over time.
           | People with deadlines and concerns of their own.
        
       | user00012-ab wrote:
       | https://news.ycombinator.com/item?id=23448489
        
       | jgarzon wrote:
       | Like almost anything when not used for the correct application.
       | Say a hammer to insert a screw. It is not a good idea. One of my
       | favorite things about using microservice, is that you can use
       | multiple languages. This can grant you the ability to use a
       | language which is better for the task, or for other programmers
       | to contribute in their favorite language.
        
         | status_quo69 wrote:
         | > you can use multiple languages
         | 
         | You can but you shouldn't unless there's a very good reason
         | (ex: there's a _very_ specific interface only available in a
         | language that doesn 't conform to the rest of your services) :)
        
       | danthemanvsqz wrote:
       | Microservices are good for scaling teams not hardware. If you
       | don't have more than one team then there is no reason to break up
       | your monolith.
        
       | MarkMarine wrote:
       | This misses some of the main reason Microservices are nice, it's
       | much easier to change code that isn't woven throughout a code
       | base. Microservices make the boundary between units defined and
       | forces API design on those boundaries. Yes, you can properly
       | design these abstractions without a service boundary, but having
       | the forcing function makes it required.
        
         | mixedCase wrote:
         | > Microservices make the boundary between units defined and
         | forces API design on those boundaries
         | 
         | No it doesn't. Google "distributed monolith" to read some
         | horror stories.
         | 
         | Bad architecture, or good architecture without enough quality
         | control over time will cause these issues one way or another.
         | 
         | There's no silver bullet for this.
        
         | allan_s wrote:
         | > Microservices make the boundary between units defined and
         | forces API design on those boundaries
         | 
         | until one engineer say "hmmm why adding a new endpoint in their
         | service while we could simply connect our microservice to their
         | database directly"
        
       | fffernan wrote:
       | For the most part this level of microservice solves the problem
       | of: New engineering leader comes in. New engineering Leader wants
       | to rewrite the entire thing cause "it sucks". Business doesn't
       | have resources to rewrite (for the nth time). New leader and
       | business compromise to create a microservice. Rinse and repeat.
       | Cloud/container/VM tech as really allowed this pattern to work.
       | The art of taking over an existing codebase, keeping it going at
       | low cost, low overhead is gone. Nobody's promo packet is fulled
       | with sustainment work. One microservice per promotion. Etc etc.
        
       | toddwprice wrote:
       | I see microservices as a people/team architecture. It's a way to
       | scale up people and define boundaries around who is responsible
       | for what, without having to standardize how everyone implements
       | what they are responsible for. Just expose it as a REST API.
       | Problem solved. And problems created. This isn't all bad, it just
       | isn't a "everyone should do this and all your problems will go
       | away" architecture. That architecture doesn't exist.
        
       | halbritt wrote:
       | This blog seems self-contradicting.
       | 
       | >The main benefit is independency
       | 
       | In the absence of independency, a service development
       | organization will hit a ceiling and fail to scale beyond that.
       | While there may be a whole host of other problems that
       | microservices does not solve, this single problem makes it
       | worthwhile in many cases.
       | 
       | That all said, implementing microservices well or even scaling
       | beyond the point where microservices become useful requires a
       | great deal of engineering discipline. Concepts like configuration
       | as code and API contracts have to become something more than
       | theoretical.
        
       | anonu wrote:
       | I read the explanation and I think the answer is still: it
       | depends. Think about it this way, in your kitchen you dont just
       | have 1 kind of knife. You probably have 2 or 3 different kinds of
       | knives if you're doing basic stuff - and maybe 5 to 10 different
       | knives if you're a top chef.
       | 
       | The same applies to systems architecture. Microservices isn't the
       | only solution or the best solution.
       | 
       | Case in point: I've worked on high-frequency trading systems for
       | much of my career. The early systems, circa 2000-2005, were built
       | on top of pub/sub systems like Tibco RV or 29West - this was
       | effectively microservices before the term was used popularly.
       | 
       | What happened around 2006 was that the latency required to be
       | profitable in high-frequency came down drastically. Strategies
       | that were profitable before needed to run much faster. The result
       | was to move to more monolithic architectures where much of the
       | "tick to trade" process happened in a single thread.
       | 
       | Point is: use the right tool for the job. Sometimes requirements
       | change and the tools needed change as well.
        
       | [deleted]
        
       | drdaeman wrote:
       | Data API over HTTP spaghetti is surely a bad way to do
       | microservices (some accidental exclusions apply[1]). And if you'd
       | have to do cross-service transaction or jump back and forth
       | through the logs, tracing the event as it hops across myriad of
       | microservices, it means that either your boundaries are wrong or
       | you're doing something architecturally weird. It's probably a
       | distributed monolith, with in-process function invocations
       | replaced with network API calls - something worse than a
       | monolith.
       | 
       | At my current place we have a monolith and trying to get services
       | right by modelling them as a sort of events pipeline. This is
       | what we're using as a foundation, and I believe it addresses a
       | lot of raised pain points: http://docs.eventide-project.org/core-
       | concepts/services/ (full disclosure: I'm not personally
       | affiliated with this project at all, but a coworker of mine is).
       | 
       | ___
       | 
       | [1] At one of my previous jobs, I've had success with factoring
       | out all payment-related code into a separate service, unifying
       | various provider APIs. Given that this wasn't a "true" service
       | but a multiplexer/adapter in front of other APIs, it worked fine.
       | Certainly no worse than all the third-party services out there,
       | and I believe they're generally considered okay.
        
         | ipnon wrote:
         | Yes, the more I develop on the Web, the more I find HTTP
         | lacking as a panacea for process communication. It's ubiquitous
         | because Web 1.0 operated at a human-readable level. It was 1
         | request makes 1 response. Now that we have 1 request makes many
         | server-side requests makes 1 server-side response makes many
         | client-side requests. There does not exist a solution now that
         | solves all of the problems of this many to many communications
         | problem on the web.
        
       ___________________________________________________________________
       (page generated 2020-06-07 23:00 UTC)