It’s over. Another day went by, and you aren’t able to make a final choice.
You’ve been thinking hard about your new app’s architecture, but you still live in permanent doubt.
“Which back-end architecture should I use?”
“Should I go with a monolith or microservices?”
I remember facing these questions some years ago when I began building Deebbler and Wakeando, two of the previous startups I co-founded.
It’s a daunting situation.
On the one hand, there is a voice in your head telling you to keep things simple.
It advises you to focus on only what’s needed and do no more than what the situation demands.
“Build a monolith for now.” — it tells you. “You’ll worry when the time comes, and everything will be alright. “
But then, there is another voice telling you to be more foresighted.
“What if I keep things simple, but I fall short?
“Go with microservices instead!” -it’s what this other voice tells you.
“Because… customers’ response is uncertain. What if I can’t fix problems and adapt my solution quickly?”
“What if demand goes high and it can’t scale?”
“What if our team grows and working on the system becomes a nightmare?”
“What if…”, wow, wow, wow! Yeah, I know, it’s a tragedy. What if your non-existent users can’t access your precious system? — note the irony.
Missing the shot.
Which voice is right? Well, the answer is not trivial a priori.
On the one hand, you may trust your conservative voice. If you kept things simple and blindly go with the monolith, you could avoid lots of headaches now and start shipping sooner.
That might lead you to future problems, but you believe you’ll overcome them if they arise. And actually, maybe they’ll never do so, whatever the case, your life will be more comfortable for now, right?.
On the other hand, you may be on the other side of the spectrum and trust your far-sighted voice’s arguments instead.
Leaning towards the simplistic style makes you feel anxious. You fear overcomplicating things, but still, you believe your investment in microservices/SOA now will pay off in the future.
Your life will be better off if you prevent potential problematic scenarios, and a constellation of services might help you with that, right?.
On the contrary, you may not have positioned yourself just yet. Do you feel in doubt and don’t entirely agree with any of those arguments? If so, then you’re closer to a better answer.
Finding the right balance.
One of the main advantages of microservices is that they allow partitioning a system into uncoupled parts, explicitly establishing solid boundaries between them.
And as DHH nicely puts it:
“…it’s a wonderful way to parallelize opportunities for improvement. Each service can be its own team with its own timeline, staff, and objectives. It can evolve independently, at least somewhat, of whatever else the rest of the constellation is doing.”
That can bring significant benefits from an organizational perspective if you’re a gigantic team like Google, Facebook, Microsoft, and the like.
However, once you hit that kind of isolation, you’ll stumble upon new levels of complexity and pain.
First, service boundaries will become very hard to change. Getting into these waters when starting up, when you are still figuring things out, with lots of moving pieces to fit in yet, is almost certainly a ticket for suffering.
…starting with microservices only works well if you come up with good, stable boundaries between the services — which is essentially the task of drawing up the right set of BoundedContexts. Any refactoring of functionality between services is much harder than it is in a monolith. But even experienced architects working in familiar domains have great difficulty getting boundaries right at the beginning.Monolith First, Martin Fowler.
But that’s not the only pain you will face. A microservices/SOA architecture leads to immense labor and operational overhead.
It’s what Martin Fowler calls the Microservice Premium.
When you get into microservices terrain, you have to worry about eventual consistency, monitoring, dealing with new types of failures, and a whole additional set of concerns that a distributed system introduces.
If you’ve never worked with distributed systems before, you might underestimate the difficulties you will face. I know it because I made that very same mistake in the past.
Splitting a system into a network of autonomous services? Sounds fun. Making services eventually consistent? I can handle it. And, hey, this framework is going to do all the heavy lifting. Easy peasy!
However, the reality is that the microservices route will probably do more harm than good. You’ll suffer more headaches now and, counterintuitively to what you may think, that will not help you avoid more pain in the future — but rather the opposite.
Almost all the cases where I’ve heard of a system that was built as a microservice system from scratch, it has ended up in serious trouble.Monolith First, Martin Fowler.
Microservices/SOA doesn’t come for free. You’ll pay a very high price you won’t benefit from unless you reach a massive organizational scale and a consolidated understanding of your business.
When you are a small-to-moderate-sized team, even if your boundaries are firm, microservices/SOA won’t likely be worthy of the additional overhead.
You might be worried about issues such as performance, scalability, or availability.
However, those are not habitual matters to worry about in the beginning.
And even later, if they become a real concern, a monolith might give you more room than you think.
Monoliths can get you far.
They all started as a monolith.
But what might be even more surprising is that they still remain that way — or spun off a few special services at most — despite their exceptional size.
And that’s a crucial lesson to take note of.
You don’t need to go all-in with microservices for working at scale. You can travel extraordinarily far with a monolith. And even if you smash into a wall, you can always extract specific parts and welcome the Citadel.
That next step is The Citadel, which keeps the Majestic Monolith at the center, but supports it with a set of Outposts, each extracting a small subset of application responsibilities. The Outposts are there to allow the Majestic Monolith to offload a particular slice of divergent behavior, either for organizational or performance or implementation reasons.The Majestic Monolith can become the Citadel, DHH.
Go the sustainable route.
Going with a monolith not only enabled the companies behind these great products to operate at scale. More importantly, it played a critical role in their success.
When going with microservices/SOA, teams have more food on the table to handle. And this can trigger a vicious cycle.
With more to handle, they get less productive and need to grow bigger to address the increasing complexity. And when teams grow bigger, the organization becomes harder, so again there is even more to handle.
Like fast food, it is a great way to make your company fat.
Microservices might serve you at some point, but if not justified at the moment, you’ll be adding accidental complexity to your company, not just technically but organizationally. You’ll have to bring more people on board, worry about new issues, and pay the toll on many dimensions.
Indeed, staying away from microservices/SOA made these businesses more efficient, helping them keep their teams smaller and more productive. That undoubtedly enabled them to grow more healthily and achieve an unfair advantage.
And here is the underlying, foundational lesson you should set in stone.
Whatever the stage you are in, keep a sustainability-driven mindset. Do not increase the burden on you unnecessarily. Seek an efficient design that can smoothly grow with your business consistently.
Choosing the monolith is one of those sustainable, intelligent decisions that will save you lots of headaches along the way.
You don’t want to accidentally make things harder for yourself.
Don’t shit on your own plate.
It would be best if you didn’t take success at the monolith for granted, however.
Don’t get me wrong. Just by following the monolith pathway, you’ll likely be in a much better place. At least in the early stages, you’ll be more agile and flexible to evolve your app and avoid the complexity excess.
But don’t fool yourself. You are not safe from making your system unsustainable just yet. Many risks are still ahead for you to confront.
The monolith vs. microservices dilemma only has to do with the physical architecture of the system.
In the monolithic style, there is a single unit of deployment running in the same process. While in the microservices approach, a system is split up into a set of independently deployable units, each running in its own process. That’s all.
A monolith is about building an integrated system, while microservices are about creating a distributed one. But integrated or distributed, your app can equally become a total mess.
Monolith or microservices won’t matter if you can’t get to the right logical design and a clean, well-structured codebase. Sooner than later, your ability to deliver value will dramatically suffer.
Leaning towards the extreme “we’ll figure it out later” mindset can make your life easier for now, but it’s an evil trap you should avoid. If you are not careful enough, you can end up in very desperate situations, with a big ball of mud and at the edge of the abyss.
That’s what happened to Groove. They started shipping fast without giving it much thought…until they suddenly hit a wall when poor design and technical debt showed up.
Fortunately, they managed to get out victorious, not without a complete rebuild of their app and after loads of money, blood, sweat, and tears.
However, you may not be so lucky.
As DHH describes it, a monolith is not enough. It also has to be majestic.
Start with a Majestic Monolith, and your future self will thank you for it.