House of cards architecture

The best analogy I’ve ever found to help explain the difference between Monoliths and Microservices

Zac Braddy
Koodoo
16 min readJan 21, 2019

--

Building software really can feel like building a house of cards sometimes. Recently (for some reason) I spent some time mulling this concept over and was shocked at the number of ways this analogy actually fits. After spending more time thinking about it (for some reason) I realised that it fit so well that it might actually make a great way to demonstrate, in a tangible way, the differences between monolithic and microservice based architectures.

Let’s begin by looking at the ups and downsides of Monolithic architecture through the frame of this novel little analogy.

Advantages of the monolith

So here is how the analogy works; a single card represents a piece of code. It might be a class or a function or a subroutine, think of it as you will, but basically the card is a piece of code that does something. The application’s purpose in this analogy is to make an aesthetically pleasing card house.

With that said let’s explore the upsides of monolithic development.

Simple to get started and not a lot of complex infrastructure required.

To build a card house all you need to get started is a deck of cards and a flat surface. Both of these can be fairly easy to source and the second you do you can get to work on building your aesthetically pleasing card house.

It is the same with building a monolith I could spin you up an express app that will return you the sum of two numbers in less than 15 minutes. The tools required to put this little monolith together can be sourced very simply and put together with little effort. This all makes getting started and getting something to market very quick.

Concepts are well understood and practiced by most professionals.

I don’t care who you are, at some stage, you’ve had a go at building a house of cards. Whether it be part of a drinking game, or you were just bored on a summer holiday before smart phones were prevalent. There are a heap of people who have tried to do this.

It rings true with development as well, in this day and age there are A LOT of people out there who are developing professionally and even more that have just given it a go. According to an IDC study in 2014 there were ~11 million professional software developers worldwide and a further ~7.5 million hobbyist developers. I’m sure at least some of them are pretty good too!

With such a wide pool of developers to choose from and the prevailing architecture for the past 20 years being N-Tiered monoliths you can be pretty sure that you could build a pretty substantial team of developers who are more than qualified to build you a solid monolith in no time! This is a strong advantage especially for companies who need to accelerate fast.

Cumulative practice of many professionals mean patterns and best practices are established.

If you’ve ever spent any time at all trying to build a card house then you almost certainly have a few favourite strategies for making the magic happen. Maybe you’ve made some up on your own or maybe your dear old granny taught you the way she used to build card houses when cards were the best games console available!

You might have seen or tried out the finger bridge method

Or maybe your more of a card bridge hanger sort of person!

Which ever way you do it you can be sure that you’ve got a good method going and more than that someone else has a better one. Put it this way, out there some where, there is almost certainly a speed card house building league.

This translates over to development as well. We have been building monoliths for LONG time now. I mean monolithic development is old enough to buy a beer in most countries these days.

Many books have been written, patterns created and iterated upon. Some principles that hold together so very well in monolithic development like trying not to repeat yourself in code (Don’t Repeat Yourself, DRY principles), these days are accepted and unquestioned as being wholly right.

It’s fair to say that as a community, developers are pretty well practiced at this type of development and we can pretty quickly identify and agree upon what makes a good monolith.

Disadvantages of the Monolith

Hidden exponential complexity and knock on effects.

You may have noticed in the gif’s above that I didn’t bother to build more than one level onto the card houses I was building.

The reality of it is that the first level is quite easy. I probably could have fairly easy added cards to the side of the ones on the first level but as soon as I started going up it got quite difficult. Even going further horizontally it equally can go wrong.

The reason for both of these difficulties is that every card is relying on every other card for support. This means that if even if I were to build a long single story card house I’d find that at a certain point I might make a wrong move adding cards or I might even just make a small adjustment to one of the cards on the left side and cause a collapse that goes all the way to the middle of the house! I wasn’t even anywhere near the middle?!

Remember that in the analogy the cards are pieces of code. This part of the analogy holds up incredibly well. In order to make changes to our card house you need to know about and conform to all the decisions made about the house in the past.

How high the teepees are isn’t really up for debate once the house is built because all the other teepees rely on the teepee next to it being that high. Equally, whenever you are making a change to the house you really have to consider the house as a whole and all the cards in it, if you don’t watch the whole house you could find yourself playing 52 pickup.

It really is the same in monolithic development. You are bound by the choices made in the past. If you’ve written your application in C# then porting the whole thing to node just isn’t really an option. Also if you are going to go fix a bug you really want to have the motivations of the original author in mind when you’re fixing the bug. Maybe they did what they did because of something else somewhere else……who knows???

Innovation can be hampered

You invested the effort and built your four story card house. Precarious though it was, you’ve persevered and you’ve delivered your card house made of red backed cards. But didn’t you hear? Everyone is talking about blue backed cards these days and unless you can say your house is made of blue backed cards, then you are way behind the competition.

TFW your product becomes legacy 2ms after release

Now of course we can just add new parts of the house with blue backed cards, but because of the imprecise nature of card houses in general, doing this is going to make it look really tacked on and unnatural. On top of that the blue cards might be a bit shorter than the red thus making lower teepees necessary.

On top of all this even if you do successfully tack something on then probably the next step will be a proposal of changing card by card in the house to blue. This might excite the tech team but everyone knows that a project to rewrite a monolith has no end date.

This part of the analogy cuts very close to the reality of monolithic architecture.The heavy interdependencies that arise in a monolithic architecture mean that there’s just no good way to make room for experimentation or innovation.

If you add something on to the side of the application it’s likely to stay there as a separate module forever and just because you built it doesn’t imply that the next thing that will happen is some massive project where you piece by piece rewrite the whole application which is what you’d really need to do to enact real change.

Monoliths also suffer from a problem where by within the code base conventions will have been formed and been followed to varying degrees of success. At some stage you get to the point where, rightly or wrongly, you start having to follow these conventions just to make things work even if you know they are the wrong thing to do.

The phrase I’ve coined for this is “Being haunted by the ghosts of shittiness past” so there is my contribution to the development communities vernacular, you’re welcome.

First class citizens sitting in coach

So you’ve completed the card house and sidelined the blue card project until Q4 of the 20-never fiscal year, and you’re now ready as you’ll ever be to start rolling out to customers. When we do the roll out we should make sure we harden the card house up in case we experience any people trying to blow it over or people intentionally bumping the table.

After we’ve done that all we have to do is work out how to move the card house from the table you’ve been working on to the table they’re sitting at….

Although we wouldn’t copy line for line to the code base to do our deployments the analogy still does a decent job highlighting a problem with monolithic architecture.

Because you can build an entire application in development quickly and easily using monolithic architecture it’s easy to prioritise building functionality over concerns like deployment and security. This often sees these important areas be a project afterthought.

Advantages of Microservices

For demonstrating microservices with card houses the rules are similar. A card is still a piece of code but we add something to our analogy here; blu-tac. The blu-tac represents infrastructure, security, deployment strategies; the all important glue of your application. We can use this to build triangles like this:

…and triangles represent a microservice. It’s a smaller structure that can live on its own but can be used as a building block to build bigger things.

Standardisation

We now have a standard unit for building our card houses, the triangle. This standardisation brings with it a LOT of benefits. First and foremost, we can move our triangles easily to the customers’ tables and we are significantly more wind resistant out of the box! This is a benefit we gain with every triangle because the standard way to apply these (blu-tac) has been thought about from the beginning.

The standardisation into units of code also means that we don’t necessarily need to build our triangles with the ENTIRE rest of the house in mind. Sure the triangles next to them might be a factor but as long as we’re building triangles that generally fit the original design we can ensure some degree of compatibility with the whole. Therefore when building a single triangle we can just focus on building the triangle and not have to keep the whole card house in mind.

For each of these benefits you can draw similarities between the card house and the development of a microservices architecture.

Generally when you start building microservices you’ll put together a template for services or a blank service generator which you can then use to start new services. These templates will be built in with considerations around deployment, security, etc. and because they are the basis of your entire system you will invest significant amounts of time getting these right.

The benefit you buy from this effort is that every time you build a new service you start from a point where the most important things to having a working application have already been thought of and now it’s just up to you to build the next application to set the world on fire.

Also with microservices you will generally build them as black boxes which send messages to each other so really all you need to worry about is how the service interacts with it’s neighbours allowing you to not have to worry too much about how the service you’re adding affects the rest of the application as a whole and just focus on the logic inherent in the service you’re building.

Scalable development

Now that we’ve scaled into our triangle way of doing things with the cards. We have gained scalability in our development practices on so many levels. Firstly look how quickly we can configure 3 already built triangles into a TWO STOREY house!!!

Good luck to the competitor card house builders is all I can say! But it’s not just the speed at which we can compose our card houses now.

Think about it, we can now build horizontally and vertically with relatively the same speed. That is something we just could not have done pre-triangles.

But the speed at which we build individually isn’t the only place we can benefit from scalability in our development.

One of the benefits that we gain from the standardisation that we spoke about in the last section is that building software from microservices makes it so much easier to have more and more developers working on the same application without negatively interfering with each other’s work.

Whilst each team member works on their services they are free to think locally and only concern themselves with how they should interact with the services immediately next to them. The positive impact of that service can be felt globally in the way it helps to provide new functionality and any negative impact globally is minimised because changing the code in one service wont affect the function of another.

Innovation

Now that we have a standard way for our triangles to interact if we decide to bend to our customers demands and introduce blue card triangles it’s a simple matter of taking our standard triangles and doing something different with them.

Whilst when we only have one blue card triangle it might still look a little odd it’s easy to introduce and easy to take out so you can experiment with the blue card triangle and if you like it you can gradually go about replacing triangles with the new blue card ones as an when you can. There’s no need to blanket change all the cards because the blue triangle is able to remain part of the whole for as long as it takes and the red triangles are unaffected. Also if you don’t like it you can just remove the blue card triangle.

What else is cool is that we can now do some pretty amazing things whilst experimenting with our card house. Amazing and creative things that wouldn’t be possible without our triangle. Like check this out:

Building an upside-down teepee with individual cards is just a near impossible feat but there you go with our new system we can just do it. More powerful than that we can just do it to try it out, and if we don’t like it we can remove it from our little house without too much of the rest of the house affected.

With monolithic architecture experimentation it is risky because if you don’t get it right you risk the integrity of the monolith as a whole. But with how segregated the codebases of microservices are, experimentation is facilitated in a way where it can, and should, be encouraged.

Mostly, we’re looking at buzz words here like Machine Learning and Blockchain. They’re entirely doable without microservices. But with an architecture that is able to be experimented in, like microservices, these things are far more doable in a real world scenario.

Tech Debt

So we’ve now built our card house and we’ve been iterating on it for a long time let’s say we want to revisit one of our older triangles and make a small adjustment. But when we go to adjust the triangle we find that the blu-tack has made the cards it was holding together all sticky and gross, and the grease stains mean that the triangle doesn’t look as much a part of the whole of the house.

We could spend time trying to save our triangle but, let’s face it, it doesn’t take that long to build a new triangle we might as well just build a new one. Also that new triangle will benefit from all the experience we’ve had building triangles since we first built this one, so you’ll probably build this new triangle better than if you hacked about the old one anyway.

Maybe the analogy got a bit contrived there but you should easily be able to see the point I’m making. This architecture can actually help you fight tech debt, in a way.

The reason being is that as you continue to work on your system and as you revisit services to tweak or add functionality you can be upgrading them with all the latest and great techniques and patterns that you’ve picked up in between the time of first building the service and now.

Disadvantages of Microservices

Complexity

Though it might seem that building our house of cards with triangles has made the whole process so much simpler if you really think about it, our challenges with building our house actually haven’t all gone away. They’ve just shifted the way they manifest themselves.

Whilst we don’t have to worry about individual cards anymore we do have to be cognisant of the fact that we are now building with different building blocks which means that there are going to have to be other problems we need to solve related to the new shape of our building blocks.

You find with a microservices architecture not everything is sunshine and ASCII rainbows. You may have thought you defeated the complexity inherent in the code but it merely retreated to another part of the system.

The complexity now lives in the infrastructure, in the way that all your services interact with each other to provide the functionality of your application. And, how you monitor your application so that you know that functionality is being provided at all. And, the mechanisms through which you’re told that the functionality isn’t being delivered and the processes through which you try to get to the bottom of why the heck it isn’t doing what you expected it too!

The bottom line is that microservices don’t make development simple once and for all. The architecture just moves the complexity from the code itself where we’ve spent the last 20 years and more proving that we’re pretty bad at being able to manage it, to the infrastructure and practices where we can have better tools and mechanisms that can help us to manage that complexity.

Out with the old patterns in with the new

I don’t think I’m going to blow anyone’s mind if I were to tell you that I only actually came up with the triangle method of building card houses specifically for this article. In changing my card house method from one that I’ve been working with since my child hood to this brand new style some of my old methods don’t work anymore.

I can’t do my hanging card bridge method from the above gif because the bridging card in the triangle method is attached to the bottom of the triangle from the storey above it.

God I love this analogy. This is absolutely true of microservices. In the time I’ve been working with Koodoo.io to build their systems we’ve found that one concept that we’ve all held to be a given in making good software DRY (Don’t repeat yourself) just doesn’t stand up the same way in microservices as it does in monoliths.

Don’t get me wrong, DRY doesn’t just go in the bin when you start using microservices. Within the context of the logic of an individual microservice there is room to DRY things up but in the context of multiple microservices DRY, in my experience, is nothing more than a fantastic way to couple services together through what ever shared code you implement across the two or more microservices that you’re trying to DRY up.

Slow to ramp up

I’m sure it wasn’t lost on any of you that the longest gif on this post was the one where I was building that first triangle. What you didn’t see before that was the deliberation I had to do around whether it would work better with blu tack or sticky tape.

There’s no getting away from the front loading of effort required to get a microservices architecture up and running from scratch. However, if you’ve gotten this far in the article then I think you’ll agree that this front loading of effort to get things right around how to develop, deploy and secure your microservices as it’s worth it. On top of that I’d go as far as to say that ultimately isn’t that much more work anyway you’re just shifting that effort to earlier in the project.

But here’s the important point, if you’re brave enough to “go dark” functionality wise earlier in the project to give yourself the time required to evaluate all the things you’re going to need to so that you can decide what your services are going to look like, you’ll reap the rewards of this effort in a big way as the project continues.

The bottom line is…

…monolithic development, in my opinion, is not the demonic force set to destroy the work of every well intentioned development team for all of eternity. It might have its downsides but as we’ve just explored microservices also has downsides.

The speed at which you can spin up a monolithic application pales in comparison to getting started on the same project using microservices which is a very attractive property for new start ups who are taking a step closer to the end of their runway each day the spend spinning up microservices.

Having said all that if those same startups have dreams of becoming the next Netflix of their business sector then the scalability, maintainability and room for innovation that microservices can offer might be worth the expended effort at the start of the project.

Really, what I’m saying is that microservices aren’t the blanket “right” answer. Sometimes spinning up a new monolith is a better alternative. Having said all that if you have the time, money and courage to get your microservices application started then….

--

--

Zac Braddy
Koodoo

Dad — Podcast host of @tabsnspacesHQ — Proglot polygrammer — So you think you can meme? — Are you still reading? He/him