Distributed big balls of mud

If you can't build a monolith, what makes you think microservices are the answer?

If you want evidence that the software development industry is susceptible to fashion, just go and take a look at all of the hype around microservices. It's everywhere! For some people microservices is "the next big thing", whereas for others it's simply a lightweight evolution of the big SOAP service-oriented architectures that we saw 10 years ago "done right". I do like a lot of what the current microservice architectures are doing, but it's by no means a silver bullet. Okay, I know that sounds obvious, but I think many people are jumping on them for the wrong reason.

From monoliths to microservices

I often show this slide in my conference talks, and I've blogged about this before, but basically there are different ways to build software systems. On the one side we have traditional monolithic systems, where everything is bundled up inside a single deployable unit. This is probably where most of the industry is. Caveats apply, but monoliths can be built quickly and are easy to deploy, but they provide limited agility because even tiny changes require a full redeployment. We also know that monoliths often end up looking like a big ball of mud because of the way that software often evolves over time. For example, many monolithic systems are built using a layered architecture, and it's relatively easy for layered architectures to be abused (e.g. skipping "around" a service to call the repository/data access layer directly).

On the other side we have service-based architectures, where a software system is made up of many separately deployable services. Again, caveats apply but, if done well, service-based architectures buy you a lot of flexibility and agility because each service can be developed, tested, deployed, scaled, upgraded and rewritten separately, especially if the services are decoupled via asynchronous messaging. The downside is increased complexity because your software system now has many more moving parts than a monolith. As Robert says, the complexity is still there, you're just moving it somewhere else.

There is, of course, a mid-ground here. We can build monolithic systems that are made up of in-process components, each of which has an explicit well-defined interface and set of responsibilities. This is old-school component-based design that talks about high cohesion and low coupling, but I usually sense some hesitation when I talk about it. And this seems odd to me. Before I explain why, let me quote something from a blog post that I read earlier this morning about the rationale behind a team adopting a microservices approach.

When we started building Karma, we decided to split the project into two main parts: the backend API, and the frontend application. The backend is responsible for handling orders from the store, usage accounting, user management, device management and so forth, while the frontend offers a dashboard for users which accesses this API. Along the way we noticed that if the whole backend API is monolithic it doesn't work very well because everything gets entangled.

The blog post also mentions scaling, versioning and multiple languages/frameworks as other reasons to choose microservices. Again, there are no silver bullets here, everything is a trade-off. Anyway, "everything getting entangled" is not a reason to switch from monoliths to microservices. If you're building a monolithic system and it's turning into a big ball of mud, perhaps you should consider whether you're taking enough care of your software architecture. Do you really understand what the core structural abstractions are in your software? Are their interfaces and responsibilities clear too? If not, why do you think moving to a microservices architecture will help? Sure, the physical separation of services will force you to not take some shortcuts, but you can achieve the same separation between components in a monolith. A little design thinking and an architecturally-evident coding style will help to achieve this without the baggage of going distributed.

Many of the teams I've spoken to are building monolithic systems and don't want to look at component-based design. The mid-ground seems to be a hard-sell. I ran a software architecture sketching workshop with a team earlier this year where we diagrammed one of their software systems. The diagram started as a strictly layered architecture (presentation, business services, data access) with all arrows pointing downwards and each layer only ever calling the layer directly beneath it. The code told a different story though and the eventual diagram didn't look so neat anymore. We discussed how adopting a package by component approach could fix some of these problems, but the response was, "meh, we like building software using layers".

It seems as if teams are jumping on microservices because they're sexy, but the design thinking and decomposition strategy required to create a good microservices architecture are the same as those needed to create a well structured monolith. If teams find it hard to create a well structured monolith, I don't rate their chances of creating a well structured microservices architecture. As Michael Feathers recently said, "There's a bit of overhead involved in implementing each microservice. If they ever become as easy to create as classes, people will have a freer hand to create trouble - hulking monoliths at a different scale.". I agree. A world of distributed big balls of mud worries me.

About the author

Simon is an independent consultant specializing in software architecture, and the author of Software Architecture for Developers (a developer-friendly guide to software architecture, technical leadership and the balance with agility). He’s also the creator of the C4 software architecture model and the founder of Structurizr, which is a collection of open source and commercial tooling to help software teams visualise, document and explore their software architecture.

You can find Simon on Twitter at @simonbrown ... see simonbrown.je for information about his speaking schedule, videos from past conferences and software architecture training.

Re: Distributed big balls of mud

I agree, that if you don´t master software development without µServices, they won´t salvage your project.

µServices are just a means to an end. But which? Evolvability. Or sustainable software production.

But are they the only means to accomplish this? Or just the latest fad?

I think, µServices need to be put into perspective. What are they? What´s their category? I call that "container".

µServices contain code. They are a design time artifact for building evolvability into software. Other containers are (in increasing size): functions, classes, libraries, components.

But containers don´t just differ in size/granularity, I´d say. They also differ in how strong they encapsulate the implementation details of the code they contain.

Libraries are opaque containers. No source code/implementation visible, just an API. Components are libraries too, but separate the API (contract) from the implementation; thus clients of a component can be coded in parallel with the component implementation. They just need the contract. This enables a kind of "industrial" software development. Division of labor becomes easier.

And then, the next level of container granularity is µServices. They go beyond components in that they require a platform neutral contract - which accidentally entails they run in their own process. And thus you can write them using different platforms.

That´s it in my view. Nothing more, nothing less to µServices. They are just another type of container. So as long as you have difficulties structuring your software using the "lower level" containers like components, libraries, classes, functions... you won´t be able to reap many benefits from µServices. Where there are monoliths today, where there is no experience with components, µServices will actually make things worse, I guess.

Re: Distributed big balls of mud

I'm a fan of microservice architecture, perhaps because I find it natural. It is little more than a rebranding of a type of the simple componentised/service-oriented architectures we've been doing for a while but that doesn't detract from its utility any more than every UI framework throwing "MVC" about makes that pattern less useful.

When a team chooses microservices I think it's important to acknowledge they have at least made a choice. This alone might be the reason their project turns out better than a more de facto monolithic design. For this reason I think it's important to have "trendy" topics so that they can get teams talking about what they're doing.

You could throw Spring, Git, functional programming and just about everything else into the same bucket of hype but I'd still recommend (at least one of) them.

Re: Distributed big balls of mud

Interesting that Adrian Cockcroft says / believes that monolith is a great way to start app dev, and that microservices really add value once the system, dev team, customers scale. Of course that leaves a large chasm in between... http://www.infoq.com/interviews/adrian-cockcroft-microservices-devops

Re: Distributed big balls of mud

Yep, the second you introduce distributed, you need to leverage infrastructure that addresses network latency, fault tolerance, message serialization, unreliable networks, asynchronicity, versioning, varying loads within the application tiers etc. etc. Otherwise you're coding it yourself, a la NetFlix OSS and I suspect that is one of the main reasons for monolithic shops not being interested. Takes top level talent at the moment, not something all enterprises have access to. I can't see how a microservice would ever be as easy to create as a class, too many human-based design decisions involved, but I do share your concern that are plenty of traps to fall into. I do agree and that monotlithic applications designed in a certain way would reap some of the microservice benefit, but monolithic would never be able to be as testable, refactorable, approachable to a new developer, or as friendly when scaling the team. I think your blog on layer vs component design (an an architecturally evident coding style) provides a very balanced view of this, particularly w.r.t testability. Lastly - In some cases, monolithic containers are optimized for a single app or binary deployment unit, but often they must host a variety to achieve density or respond to business pressure to leverage expensive investment(s). Using microservice approach you can tweak each container for the purpose and context at hand. As vendors start to provide some of this "missing" infrastructure, devs will naturally be more free to concentrate on the design decisions inherent in distributed systems and will be less prone to err.

Re: Distributed big balls of mud

When we were building CORBA systems in the 90's, we talked about a lot of the same benefits as the Micro-services folks are now. Then the industry seemed to cool on distributed objects, even Martin Fowler declaring "Don't distribute your objects", mostly because of latency. Wondering why distributed Micro-services are good, but distributed objects are bad?

Re: Distributed big balls of mud

I was just getting started with Java/EJB in those days but here's a few things I can think of that have changed, making the design pattern more viable today 1.) advent of PaaS/Virtualization, making it easier to provision and operate on tightly bound code-to-container-to-OS environments - that wasn't around in CORBA days 2.) faster network in general, at least within data centers 3.) better caching technology, messaging technology 4.) simpler, more universal wire protocols like REST/HTTP

CORBA vs. microservices

CORBA has object brokers through which business logic is accessed - those brokers hide physical location of objects and might lead to performance issues, because developer might not differentiate between local and remote calls. Of course this is possible with microservices, but less likely. Moreover CORBA maintains brokers, counting its references, this is statefull by design and for that reason less scalable. Microservices, especially based on REST, are better in this aspect. All above it based on my limited knowledge of CORBA.

Re: Distributed big balls of mud

Late to the party but... "Caveats apply, but monoliths can be built quickly and are easy to deploy, but they provide limited agility because even tiny changes require a full redeployment." This seems really irrelevant to me from an architectural perspective. The key to a distributed design is how the interfaces are exposed. How the system is deployed is not an architectural concern but more of a operational one. For example, lets say I have 3 servers and 3 services (to keep things simple.) I can build one thing and deploy it to three places. One build, three deployments. Every time I change one service, I build, test, and deploy the bundle. Or, I coule have three builds and deploy them to a) one server each, or b) to each server. If I pick a, I have a lack of resiliency. One server goes down and one or my services goes down and for sake of argument (and in my reality), all need to be operational in order for the business to operate. So we are down. That's bad so we'll go with b. So now, I've go three services running on three servers. 3 builds, 9 deployments. And to anyone consuming my services, it looks exactly like the bundled deployment. OK so now we want to change one service. We can just change it and deploy that alone. So one build, 3 deployments i.e. the same number as for the bundled deployment. But what about testing? In theory, you can just test the one thing and if your services are really independent of each other, then it might make sense to do this. But in my world, everything is related. Services need to be interoperable. One service consumes the things created by another. Consumers need to be able to call multiple services and derive things from the combinations of their responses. So not testing everything is crazy. We've moved away from independently deployable services because they created to development overhead, interoperability problems, and operations headaches. The benefits on a rational platform are basically a faster deployment from say 10 seconds to maybe 5. Not worth it. We might consider dividing the bundles by domain but we're leaving the idea of independently deployable services and not looking back.

Re: Distributed big balls of mud - Build Big Dams - Engineer

HISTORY PATTERN - Lessons Learned - We learn nothing from past lessons from other fields. Joke humor: Philosophy >> Science >> Math >> Engineering >> Technical >> Computer Science >> Coding >> ARCHITECTURE >> real world >> Philosophy. We just go around in circles from IBM Mainframes - Z to Linux to Virtual Machines to Cloud to Android Dalvik to MALWARE or Anti-Patterns BIG BALLS OF MUD and back to IBM Mainframes?! Proof it! Mud hut >> ball of mud baked == brick building >> Steel building >> steel titanium is too thin and VIBRATES in the wind. so tall buildings have BIG BALLS OF MUD STONE as energy dampers. The Office Tower does not sway back and forth with the Big Ball of Mud Stone. Is this explanation clear? or is it the philoso-social- virtual-software architecto PRESENTATION as clear as a BIG BALL OF MUD. Please note: the USA DAMS made from BIG MUD Concrete were built on top of karch or limestone foundations that are shaky. The acceleration of earthquakes due to oil fracking, geo-engineering, etc means we should be concerned about BALLS OF MUD

Re: Distributed big balls of mud

You have a valid point. Moving to microservice architecture does not guarantee the success of the system. But there are some advantages of microservices which cannot be denied, things like having smaller systems, or services, which can be easier to manage and develop. Of course that the effort is not gone and it was just moved somewhere else, but it definitely makes developers more productive by having more confidence and control over a smaller system. From my point of view one should start with a monolithic architecture and only move towards to a monolithic architecture when it makes sense.

Re: Distributed big balls of mud

I fully agree! If clueless (and even some otherwise intelligent) software developers/architects think microservices are awesome because they enforce clear APIs provided by services then they've missed the last 2 decades of what basic Object Oriented design 101 has been preaching - either that or they haven't been disciplined enough to practice what makes for highly productive, low maintenance code bases. This points to major flaws in hiring practices at the architecture and developer levels much more that issues with monoliths or microservices. In a well designed monolith with proper separation of concerns, APIs, service and repository classes and a decent ORM there is no architectural difference between that an microservices. The main difference becomes one of 'plumbing' - how the services are connected. In a real life microservices project I have worked on we have seen Java-Java calls in the monolith which used to take microseconds to perform explode into snail pace, high latency calls because of the new plumbing: Java objects->JSON Translation -> 'network reliability compensator kludge' -> network -> JSON Parsing -> Java object -> Do the real work, produce a result and then the return trip: Result -> JSON Translation -> 'network reliability compensator kludge' -> network -> JSON Parsing -> Java -> Process the result I've worked on well designed monoliths where the developer productivity is exceptionally high but recently had to work on a microservice 'architected' system and the developer productivity orders of magnitude worse because we're forever dealing with 'plumbing' issues between the modules and massive amounts of configuration for each module because it needs to be told where all the other modules are - that's handled by a once off <dependency> element in a maven pom.xml file in the nirvana I now pine for again...

Re: Distributed big balls of mud

I think the industry needs a term that differentiates a monolith built as a ball of mud (some definitely are) from those built using a well designed, object oriented, separation of concerns, lowly coupled, component based architecture - i.e. the 'somewhere in the middle' scenario that you mention in your diagram. The trouble is that the microservice junkies have 'framed' the word 'monolith' as something 'bad' when the component oriented 'something in the middle' monolith case is actually micro service/component oriented without the innefficient, unreliable issues of RESTful 'plumbing'. In fact a microservice/component oriented monolith is actually more 'nano' because the granularity can go as low as you like eg., class level, without any ill effect on performance or productivity!

Add a comment Send a TrackBack