- Microservices are the cure to, rather than the cause of complexity. All applications will become complex, beyond a certain point microservices will help us manage that complexity.
- Microservices come with costs and benefits. If the benefits don’t outweigh the costs, you won’t have a good time with microservices.
- There is no such thing as monolith vs microservices. There is actually a spectrum of possibilities between them. If you have pegged yourself at either extreme of the spectrum then you are missing out on the rich variety of architectures to be found in the middle.
- We can stop our journey to microservices somewhere in the middle of the spectrum, what I like to call the hybrid model. At this point we might have some big services mixed up with some smaller services. We can have the best of both worlds: the simplicity and convenience of the monolith and the flexibility and scalability of microservices.
- We should stop talking about monolith vs microservice and instead have a more nuanced debate about right-sized services.
“In many ways, microservices is a zombie architecture. Another strain of an intellectual contagion that just refuses to die. It's been eating brains since the dark days of J2EE (remote server beans, anyone??) through the WS-Deathstar nonsense, and now in the form of" microservices and serverless.”
David Heinemeier Hansson (source)
With the recent blog post from AWS saying they have ditched microservices and returned to the monolith, the old war of monolith vs microservices has reignited.
What’s your position on this? Are you team microservices or team monolith? What if I told you the distinction was something of a fantasy and that people are fighting over a fiction: microservices vs monolith is really just one part of the bigger story.
The article from AWS has been taken as evidence that they (as a longtime proponent of microservices) have backflipped on microservices and gone back to the monolith. Despite the title of their blog post being obviously calculated to get attention, the article actually seems to be about their conversion from functions as a service to what is now arguably a microservices architecture, if not a distributed application with services that are larger than micro (however you define micro).
But the point I’d like to make is that it doesn’t really matter. This is just one team at AWS acknowledging that their first attempt at an architecture didn’t work out, then they tried a different architecture and it worked better. But so what? From what I have seen in my career, this is just the normal way that good software development should work.
We all want to focus on what's most important: doing the right thing for our customers. Taking sides in the debate of microservices v. monolith gets in the way of that. Sometimes we need microservices. Sometimes we need a monolith. (I’m not yet convinced I’ll ever need FaaS - but I’m keeping an open mind). Most of the time though we are better off somewhere in between these extremes.
Sure, microservices are more difficult to work with than a monolith - I’ll give you that. But that argument doesn’t really pan out once you’ve seen a microservices architecture with good automation. Some of the most seamless and easy to work with systems I have ever used were microservices with good automation. On the other hand, one of the most difficult projects I have worked with was a large old monolith with little to no automation.We can’t assume we are going to have a good time just because we choose monolith over microservices.
Is the fear of microservices a backlash to the hype? Yes, microservices have been overhyped. No, microservices are not a silver bullet. Like all potential solutions they can’t just be applied to every situation. When you apply any architecture to the wrong problem (or worse, were forced to apply the wrong architecture by management) then I can understand why you might come to passionately hate that architecture.
Is some of the fear from earlier days when microservices were genuinely much more difficult? 10 years ago microservices did make development significantly more difficult. But the tools and platforms have come a long way since then. It’s easier than ever before to create good automation that makes working with microservices a much more seamless and enjoyable experience.
Maybe some of the fear comes from the perceived complexity? I do think this is a big part of it. People naturally fear (or at least avoid) complexity. I say perceived complexity because it’s not just microservices that get complex. Every monolith is going to become complex as well… you just have to give it some time. Whereas with microservices the complexity is just out there for all to see and we have to deal with it early—in my book, Bootstrapping Microservices, I call this bringing the pain forward to earlier in the development process where it’s easier and cheaper to deal with.
Unfortunately, it’s not really possible to hide from complexity in modern software development. Our applications are growing larger and more complex—even the humble monolith will become more complex than any one person can deal with someday.
We can’t avoid complexity in large scale modern development. What we need are tools to help us manage the complexity so that it doesn’t slow us down or overwhelm us.
"You must be this tall to use microservices."
Martin Fowler (source)
Building distributed applications, not just microservices, requires a higher level of technical proficiency. Managing a fleet of many services instead of just one means we must have tools to automate the management of the system. There’s also a lot to keep track of just trying to understand what our services are doing. The communication between services becomes exponentially more difficult to understand the more of them we have.
If you are a small team or small project, if you are applying microservices to a situation where they really aren’t warranted, or if you aren’t willing to pay down the investment in skills and technology required to build and run the distributed system, you can’t expect to have a good experience with it.
Another possible pain point is if you aren’t aligning your services appropriately with the domain. I have seen microservices applications aligned with technological needs rather than business needs—leading to too many services and an avoidably overwhelming system to manage. There really is such a thing as making your services too small, unnecessarily amping up the complexity and difficulty of managing the system.
If you can’t align your architecture correctly with your domain you are going to have massive problems irrespective of whether you are using a monolith or microservices—but those problems will be massively amplified the more services that you have. Microservices aren’t just good for scaling performance, they will of course also scale up whatever problems you already have.
"If you can't build a monolith, what makes you think microservices are the answer?"
Simon Brown (source)
Is the real problem with microservices just that they scale up the problems we already have?
A bad microservices implementation is going to be at least X times worse than a bad monolith, where X is the number of services in your distributed application. Actually it’s even worse than that, given the exponentially increasing communication pathways in a distributed application.
If you don’t have the tools, techniques, automation, process and organization that work for your monolith, what makes you think you can scale up to microservices? You need to get your house in order before you can scale up.
Microservices don’t just scale for performance and the dev team, they also scale in difficulty. If you struggle to build and maintain a monolith, scaling to microservices isn’t going to help you.
A microservices application is really just a monolith, but with the number of services dialed up and the sizes of the services dialed down. If you are struggling with a monolith and think microservices are the answer, please think again.
I like to think that microservices are not just scalable for performance and development, they are also scalable in difficulty. Microservices come with benefits, but they aren’t without their costs.
"Microservices are not a free lunch."
Sam Newman (from Building Microservices)
What are microservices really about? Why would we divide up our application into separate services?
There’s a bunch of well known benefits:
- Dev team
- Fault tolerance
- Independent (and less risky) deployment for rapid development cycles
- Developer empowerment
- Designing for disposability
- Managing complexity
But the benefits aren’t the whole story. There are also costs that must be paid:
- A higher level of technical skill
- Better automation, management and observability systems
- Dealing with the scaleable difficulty
For any tool, technology, architecture, or whatever that we want to use, we must start by asking ourselves the question: do the benefits outweigh the costs? When the benefits do outweigh the costs you will have a good experience using that technology. When they don’t, you will have a bad time.
“Microservices enable the continuous deployment of large, complex applications.”
Chris Richardson (source)
Microservices have a ton of benefits, but the real reason we should use them is because they can help us manage the growing complexity in our application.
That’s right, you heard it here, microservices are not the cause of, but the cure to, complexity.
All applications are going to become complex, we can’t avoid that even if we are building a monolith. But microservices give us the tools we need to break up that complexity into smaller, simpler, and more manageable chunks.
Microservices help us manage complexity by breaking it up into simple, yet isolated, pieces. Yes, we can also do this with the monolith, but you need a very disciplined and proactive team to keep the design intact and not degenerate into a big ball of mud.
We can use microservices to create abstractions and componentize our software. Of course, we can do this kind of thing as well with a monolith, but microservices also give us hard and difficult to breach boundaries between components, not to mention other important benefits like independent deployments and fault isolation.
“There is not one architectural pattern to rule them all”
Dr. Werner Vogels (source)
I asked you a question at the start of this article.. Are you team microservices or team monolith?
Coming back to the title of this article, it’s not a one or the other choice. There’s actually a sliding scale from one big service (the monolith) to many tiny services (microservices) with many other viable choices in between.
It’s not just monolith vs microservices, there’s a whole spectrum of different possibilities. If you fix yourself to either team monolith or team microservices you are missing out on the rich variety of architectures in between.
You don’t have to artificially align yourself at either end of this spectrum. You don’t even have to peg yourself to any particular position within it. There is no right position, despite what some people want you to think. The location you choose has to be appropriate for your team, your business, your project, or your customers. Only you can decide where you should be on the spectrum of possible architectures.
The benefits that come from microservices will come as you move to the right on the spectrum of possibilities. But moving to the right also has costs and difficulties. So we need to be sure that the cost of moving towards microservices is one that we are willing to pay.
If you aren’t trying to manage complexity, don’t need the other benefits of microservices, or are struggling just to manage the automation and technology for a single service, you should be sticking as close as possible to the monolith on the left side of the spectrum. To the extent that you need microservices you should be moving closer to microservices on the right side of the spectrum.
It might not be worth pushing all the way to the developer’s utopia of microservices due to a diminishing return on investment, but going part of the way there can yield a high return on investment.
But it’s important to realize at this point that we don’t actually need to reach (what I like to call) the developer’s utopia of microservices in order to start getting the benefits of microservices. In fact, any amount of movement we make towards the right hand side of the spectrum will bring tangible benefits even if we don’t reach all the way to the other side!
There’s good reasons why we don’t want to push all the way to perfect microservices (for a start, who gets to decide what perfect means?) As we start pushing towards the right we’ll start to see big payoffs. But as we continue to push further there will be a diminishing return on investment. The more we push towards smaller services the more the cost will outweigh the benefits. In the real world (it’s messy and complicated out there) it’s difficult, not to mention unnecessary, to achieve anyone’s notion of perfect microservices. But that doesn’t mean moving in that general direction doesn’t help.
If we don’t need to push all the way to microservices, then where do we stop? The answer is somewhere in the middle that has a set of trade offs that improve our development speed and capability where the cost of development does not exceed the benefits.
I like to think of somewhere in the middle as the best of both worlds. Yes, we can have a monolith (or multiple monoliths) surrounded by a constellation of microservices. Am I some kind of heathen that I take this pragmatic position? The practical benefit is that I can mix and match the benefits of the monolith with the benefits of microservices. The convenience and simplicity of the monolith for much of the codebase, and the flexibility, scalability and other benefits of microservices that I can leverage when I need them make for an ideal environment. I can also incrementally excavate individual microservices from the monolith whenever it becomes apparent that certain features or tasks can benefit from doing so.
The hybrid model isn't a new idea. This is actually what the real world often looks like (somewhere in the middle), despite the arguments that continue to rage online.
DHH (very much in team monolith) even seems to like the idea, which he calls The Citadel Architecture.
‘Perhaps “micro” is a misleading prefix here. These are not necessarily “small” as in “little. Size doesn’t actually matter. ”’
Ben Morris (source)
The smaller our services, the more micro they are, the less useful they will be and the more of them we’ll need. The level of difficulty goes up as we reduce the size of our services and increase the number of them.
Maybe we should stop focusing on the “micro” part of microservices. I think it’s making people try to make their services way too small—and that’s a guaranteed way to have a bad time with microservices.
I’m not sure how we even got so fixated on making them as small as they possibly can be. The intention is to be able to split up our software into pieces, separating out the responsibilities, where each of the parts is simpler than the whole. Thus making it easier to manage the overall complexity of the system. But when we make our services too small we risk being swamped by the complexity instead of managing it.
Even though everyone seems to have their own notion of how big or small a microservice should be, the reality is that there is no fixed size that a microservice should be. The “microservice police” aren’t patrolling for offenders.
So let’s stop arguing about the size of our services and instead start talking about “right-sized” services, that is to say, whatever the right size is for our situation, be that monolith-sized or somewhere on the smaller end of the spectrum. Our services, no matter how big or small they are, should be organized around our business and be appropriate to our domain. The size is almost an afterthought, it’s the overall organization that is important.
It’s not about making our services as small as they can be. In fact, beyond a certain point, making your services smaller is counterproductive. The smaller they are, the more they have to communicate with the rest of the system to get work done. The more communication we have, the more we’ll pay the network transfer cost. Not to mention that it becomes much more difficult to understand who is talking to who. We need a good balance between service size and how chatty our services are (thanks to Damian Maclennan for bringing me the term chatty).
Choose a size for your services that’s meaningful to you. And it doesn't matter if some of the services are bigger than others. Please don’t let your OCD make your decisions on service size, that can really get in the way of what could have been a great architecture. There’s nothing inherently right or wrong about making them bigger or smaller, so long as you find something that works for you.
“Just to be honest - and I’ve done this before, gone from microservices to monoliths and back again. Both directions.”
Sometimes we have to try new things in order to understand if they are a good fit for our project or not. So don’t be afraid to try new technologies. Don’t be afraid to try microservices or the hybrid model and see if it works for you.
But later, don’t be afraid to change your mind and roll back whatever previous decisions you have made. It’s not a bad thing to admit that something hasn’t worked out. Really, that’s exactly what we need to do to find success. Try different things, do different experiments, then just move on from the ones that didn’t work out. Just because microservices didn’t work out for you on a particular project doesn’t mean that they are a bad choice for other teams or other projects.
Or better yet, just keep an open mind. That’s the best way to not shut yourself off from new ideas and new thinking that could be really what you need to truly shine in your next project.
Learn more about microservices with Bootstrapping Microservices:
Learn more about fast and effective development across the stack with Rapid Fullstack Development: