Microservices, Monoliths, and Modularity

Iceberg

 

There are very valid reasons for considering a microservice architecture (MSA) when building/evolving an application. In my opinion, however, forcing modularity isn’t one of those very valid reasons.

Just the other day, I saw tweet from Simon Brown saying this same thing:

I still like his comment from two years back: “I’ll keep saying this … if people can’t build monoliths properly, microservices won’t help”. I believe that if you’re having problems building a monolith properly, trying to use a distributed architecture to force modularity may actually cause harm.

MSAs, like any distributed application architecture, involve increased complexity and costs; table stakes, if you will. Like an iceberg, there’s both a lot more to it than just what’s showing above the waterline and a fair amount of hazard for the unwary. If a development team cannot or will not comply with design guidelines (e.g. modularity requirements), injecting additional complexity is probably not the solution you need.

Distributing an application makes it harder to accidentally entangle different concerns, but it doesn’t make it impossible:

I’d argue that making it harder to accidentally break modularity addresses neither of the groups I mentioned earlier: those that cannot or will not comply. It’s ironic, but those who fail to understand the need for modularity can be very creative in their “solutions”, regardless of the obstacles. Likewise, those who refuse to comply.

In short, distribution as a means of “ensuring” modularity fails the fitness for purpose test.

The situation becomes worse when you factor in the additional complexity inherent in a distributed system. Likewise, there’s the cost of the table stakes (infrastructure, process, staffing, etc.) mentioned above. Of course, having abandoned the principle of cause and effect, one could attempt some “creative” workarounds to avoid having to pay the price (in other words, adding more and more complexity).

When you introduce significant additional complexity (with all its attendant risk) with little chance of the technique actually achieving its goal, you’ve caused harm.

These concerns are not solely limited to the application architecture. Distributing the data architecture has the same limitations in terms of ensuring modularity and introduces additional complexity. Adding boundaries adds the need for governance. A disciplined, monolithic team can maintain modularity in a monolithic data architecture. Multiple separate teams trying to share a monolithic data architecture will either experience a crippling level of governance overhead or a complete breakdown in modularity.

MSAs can be useful when you need independently scalable and replaceable components. When you have multiple teams working on one logical application, they can also be appropriate as well. Using the technique when the cost outweighs the potential payoff, however, is a losing bet.

12 thoughts on “Microservices, Monoliths, and Modularity

  1. I worry about counting on “disciplined” when it comes to people. I think that some form of governance is needed even in a monolith scenario. Perhaps it is a matter of degree?

    Like

    • Agreed 200% (inflation 🙂 )

      Passive measures, whether structural (“let’s distribute the components so people can’t break modularity”) or procedural (e.g. “be disciplined”), will not be sufficient. Governance at the application level (which is, IMO, the application architect role) and above is absolutely necessary to help reconcile competing interests and monitor that the design is not wandering down some dark alley. It’s critical to bear in mind that this can happen by misunderstanding, lack of experience, non-compliance, or even incoherence in the design. Someone needs to be monitoring what’s happening and equally important, why.

      Liked by 1 person

  2. Would it not be better if we draw a clear line between them as two different level of software architecture:
    -How it is structured as a set of implementation units (Module View)
    -How it is structured as a set of elements that have runtime behavior and interactions (Component & Connector View)

    Different view of software architecture is extensively discussed in a book called “Documenting software architectures views and beyond” (http://www.worldcat.org/title/documenting-software-architectures-views-and-beyond/oclc/935826021)

    Liked by 1 person

    • To an extent, yes. That being said, it must be remembered that two views of the same thing, though they may focus on different aspects, still point to the same thing.

      The point that Simon and I are making is that trying to “enforce” separation of concerns via distribution is neither fit for purpose nor does it come without significant performance and complexity costs.

      Liked by 1 person

  3. Pingback: Java Annotated Monthly – July 2017 | IntelliJ IDEA Blog

  4. I agree whole heartedly with you. But there is one thing I’ve always wondered, and I do think has to be evaluated with what you are saying. How “much” modular is my solution. A module is self contained and works (scales in a MSA world) independently from others, but a module has to be used for something to be useful. And the more useful it is it will be used in a lot of different contexts. But now other modules are dependent on this module and thus they are not “equally” modular. So how do one know how modular my modules are if the usage is eventually breaking it apart? And the dependencies are set by the requirements and they too evolve over time.

    Like

    • I’d disagree with the self-contained part. Pretty much there will always be dependencies. The question is more one of how cohesive the contents of the module are and how well managed the dependencies are.

      As a secondary note, this is one of the areas where the module/microservice equivalency breaks down – a module may not necessarily be a process (which would be self-contained), where a microservice would.

      Liked by 1 person

      • So how do I know that a module with a module dependency shouldn’t be a single module or those modules should be split up in three different modules? And how do I know that I made/created the right module in relation to everything else?

        I agree with the notion that a module is not resrtricted to a separate runtime, several modules could run in a specific runtime. Just because you deploy it in a different runtime than everything else doesn’t make it a module or modular per se.

        Liked by 1 person

      • Hi Henrik,

        The short answer to the “how do you know” questions is that you don’t know that your decisions are the right ones. The best you can hope for is that your decisions were intentional and made sense in light of the information you had at the time you made them. The optimal case is that your physical structure is designed to enable what’s important to you. This post goes into more detail.

        Regarding runtime, that’s not the only dependency I had in mind. Third party libraries are another consideration.

        Liked by 1 person

  5. Pingback: Microservices or Monoliths – Fences and Neighbors | Form Follows Function

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.