Introduction
Hello there, dear reader! Well, if you’re reading this I assume that you probably have already a basic understanding of how the web works and you probably got a few things done by yourself as well, so congrats on that!
The next big step is to understand a few of the patterns and architectures that exist out there. Not only that will make your software building more consistent, but also, way more solid too — from scalability to maintainability.
This article will explore two of the most popular software architectures: the monolithic architecture and the microservices architecture (with some other important concepts in between).
As always, we have a bunch of discussions regarding which of them is better and the answer here is as always the same: there’s no silver bullet, you should learn which are the cases for using each of them and how to transition between both as well to be a rational engineer.
First one: The Monolith
In case you’re unfamiliar, the monolithic architecture is one of the most traditional ways to design software applications. In this approach, an application is built as a single unit — which we call the monolith — where the components of the software are interconnected and interdependent.
This architecture is characterized by a single codebase (usually using the MVC pattern), shared database, and typically a single deployment unit.
Advantages
Monolithic applications are often simpler to develop, especially for smaller projects or teams. They have a straightforward development process since the interactions between different parts of your application reside in the same place — this also means that there are generally fewer API calls and fiddling data around to make stuff work!
In terms of deployment, it generally is easier as well. Since you have a single unit, once you deploy it, everything should be up and running, meaning you don’t have any extra work on that.
When we talk debugging, it is generally simpler because the entire application runs within a single unit (which means you generally don’t have to jump around between multiple applications, trying to find the problem). End-to-end testing can also be easier and can run smoothly through entire journeys.
Disadvantages
As the application grows, a few challenges start to appear. The first one is organization-wise — since everything is in the same place keeping the context of a really big application and all the ramifications it goes through starts to become really hard (of course, there are ways to plan ahead — e.g. the Modular Monolith, for example — for that, but, when you build fast, this generally are not thought through).
The second one is scaling per se. Since the whole application is inside a single unit, specific usage-intensive points of your application will share the same resources as your whole app. This generally means that scaling things becomes a more complex task than just “pay more server power” or “rewrite that part in a different tech”.
Microservices Architecture
Now, the general alternative to a Monolith is the Microservices architecture. It’s an approach to developing a single application as a suite of small services (that’s where the micro comes from), each running in its own process and communicating with lightweight mechanisms to keep it all running. They can usually be developed, deployed, and scaled separately. Each service typically has its own database and communicates with other services through well-defined APIs.
It also has its own patterns of organization (which there are a ton of famous books about) where one of the most common ones is DDD (Domain-Driven Design).
Advantages
The first and most obvious one is scale. Microservices can be scaled independently, allowing for more efficient resource utilization throughout the segments of your app. Since everything has to communicate as a black box, this architecture also provides flexibility in choosing technologies for different services.
The second one is that when we are talking about really big apps, the complexity of the code of microservices is distributed between them. This generally means that, if a microservice has a bug, it’s simple to send a new engineer of the team to go take a look at it — there’s not that much space where this bug can exist anyway.
Disadvantages
The first one is that making all those things communicate and interact properly can be a real challenge. God only knows how much time an engineer is capable of spending trying to find why messages from Kafka are not arriving or any other weird problem that can happen. Managing all that, their infrastructure, and deployments can be hard.
The second one is that the context is more segmented — this can be a good thing when we look at it coming from the point of view of learning the code base, but this can be a pain when looking at it as learning the product — it’s way easier to follow if your code goes through 5 files than 5 different apps.
The last one is that microservices have a caveat which is Latency. If they’re not designed properly, it’s quite possible that the separation of concerns and expected speed increase will not pay off since now you also added a bunch of different calls for them all to communicate.
And sometimes, when people create new stuff, they try to fix part of those problems, which is part of the feature set of Encore, the sponsor of this article:
A great standout feature for me is that you don’t need to worry about the communication between different microservices as much as you’d normally have to. It’s a really great idea — you have almost the same developer experience as when you’re working with a monolith, but, with all the scaling power of a microservice.
There are also a ton of features to make the deployment process of multiple services easier as well. They’re really trying hard to make that bridge of having the best of both worlds happen and it would be awesome if you could check them out and give them a star!
Choosing the Right Architecture
When deciding between architectures, you'll need to consider your application's growth potential, team size, and how complex your product actually is.
The simpler your app is, the more you can benefit from a monolithic approach. If you’re in doubt, the safest choice is going with a monolith — you can always break things apart later, but, stitching things up is HARD (here’s a great source to read if you’re still in doubt: Monolith First)
Architecture | Key Benefit | Key Disadvantage | Best For |
---|---|---|---|
Monolithic | Simplified development, deployment and debugging | Growing issues | Small to normal-sized applications and MVPs (e.g. DEV.to is a monolith!) |
Microservices | Independent scaling of components | Complex management | Really large applications with multiple teams (e.g. Netflix uses a ton of microservices) |
As complexity grows, you might want to consider breaking things apart, so, let’s talk a little bit about how can you convert a monolith into a series of microservices.
Converting: How to migrate from monoliths to microservices.
There are a few ways to migrate from a monolith into the microservice world. Let’s quickly go through them:
- Greenfield Replacement: Simply creating things from the ground up — not having constraints from prior work can be really beneficial in some cases. But, of course, we have a bunch of inherent possible problems here (how long will it take? how much time will users suffer? etc)
- Brownfield Replacement: New architectures should coexist with live software. When we’re talking about brownfield replacement, there can be a lot of pain and headache in coexisting things with old/problematic software. An interesting approach to solve on how to tackle this problem is the Strangler Fig pattern, where, we’ll generally wrap, little by little as a strangler fig, the old code and redirect it to newer code, eventually killing it. This makes the transition more smooth and also less risky.
Generally, here are the steps we are going to take:
- Identify clear boundaries within the existing application.
- Gradually extract services, starting with less critical components.
- Implement new features as separate services
- Refactor the existing codebase to support the new architecture
- Ensure robust testing and monitoring throughout the migration process → Nothing is as hard as changing your application blindly
Conclusion
Hey! We've gone through quite a journey here. We talked about two main architectural approaches: the good old monolith (simple, and straightforward, but with growing challenges) and microservices (flexible, and scalable, but way more complex to manage).
I hope that you’re now able to choose things (or at least have a great gut feeling) for the next choice you’re going to make, but, remember: there's no "one size fits all" - if you're starting something new, go with a monolith first if not, think it through!
At the end of the day, what matters is picking the right tool for the job. Understanding these patterns will help you make better decisions for your specific needs. And remember: you can always change things later - just make sure you have a solid plan for that transition!
Top comments (19)
Monolith has nothing to do with MVC as well as microservice is not defined by API. Both can be developed by DDD aproach. Microservice is socio-technical solution to big problems where a single team is not capable to manage due to communication overhead among the team members. Microservices address complexity in scale, not scaling performance or space.
Hey @vaclav_prokop_02453acfbd7! Thanks for the comment! I'll do my best to disect your comment below.
So, for the first part of your comment:
I find it really hard to say that Monolith has nothing to do with MVC, since all most popular monolith frameworks like Ruby on Rails, Laravel and Django start out of the box with the MVC pattern. So, yeah, it has a lot to do with the MVC pattern and if you pick a Monolith at random, it will most probably use it.
But, I totally agree that this is not necessarily true in all cases, you can find Monoliths implementing other architectural patterns, like DDD, that's why I wrote:
The same argument is valid to the other point:
While technically true, APIs are so prevalent in microservices implementations that they are almost inseparable in practical discussions. It's hard to explain one without mentioning the other.
For the part:
True! That's an important and often overlooked historical perspective on microservices—great point!
For the last part:
I might be misunderstanding this part, so feel free to clarify. That said, I see scaling performance or space as facets of scaling complexity, which microservices often address as part of their design goals.
Lastly, I'd like to remember that this piece is focused for general beginners/intermediate level software engineers. This means that, although all those nuances exist in the software ecosystem, I intentionally simplified some aspects to make the article more approachable.
Thanks again for the comment and looking forward to seeing you around ;)
Hi Lucas, I appreciate your intention to popularize complex concepts among beginners. However, my intention was to align concepts at the same level. We have a serious problems in programming and overall architecture thoughts. That is mixing different levels of concepts toghether. I see it in code every day, and it can be seen in articles on the internet too. Just as classes in a code can represent different level of abstraction, architectural patterns serve different purposes too. What I mean is: MVC is a pattern for implementing REST services API. SOAP service can be implemented by another catchy pattern, but in principle both are implemented by some sort of decision chain design pattern. Patterns and APIs exist on a lot of different levels, such as code implementing these. It can be confusing, I know. I see that confusion among professionals making me unhappy.
Hey @vaclav_prokop_02453acfbd7, thank you for the thoughtful comment—it’s clear you’re passionate about the nuances of architecture and abstraction levels, which is something I really respect (and aim to be hahahaha).
I understand where you're coming from regarding the mix of abstraction levels in architecture discussions. It’s true that patterns like MVC or REST often get conflated with broader architectural concepts, which can muddy the waters when explaining these ideas -- to be fair, it's also hard to separate each concept in its own box since they all come together as a whole. My goal with this piece was to introduce these concepts in a way that’s approachable for beginners while staying grounded in practical realities.
Your point about different levels of abstraction—like MVC for implementing APIs versus larger architectural decisions—is well-taken. It's a challenge to balance simplification and technical precision, but I’ll make sure to take your feedback into account in future articles to try and make those distinctions sharper.
I’m also super curious to hear your thoughts on how you typically communicate these differences when mentoring or explaining to others. It’s always great to learn from someone who has clearly spent a lot of time thinking about these challenges.
Thanks again for your input—I really appreciate it!
Microservices are only useful to large companies. The rest of the world can very well do with a monolith. A monolith can still be designed in a modular way so that most of the disadvantages are addressed. Microservices requires a lot of orchestration which is difficult and tedious. That is something that is not often mentioned in articles and if done wrong lead to a very expensive solution.
Hey @retakenroots! Thanks for the comment and I agree with a lot that you said! So much so that this article was largely inspired by this video of DHH.
As I mentioned, if you're in doubt, there's a great chance you're going to be better suited with a monolith!
Thanks and see you around ;)
I'd like to understand this more. I am working to develop microservices specifically because I don't want to orchestrate development by other groups, nor do their programming. I want to build the platform, offer services and when they build content, leverage it for my group. Is this a bad idea? Are there better architectures I should use?
I have no problem that you promote the capabilities of your company.
The post contains a lot of information, But it is not balanced. It leans to microservices.
As an example:
With pay more server power you reference vertical scaling. But you never address horizontal scaling, where different servers run the same application.
You wrote it in the context of having a pressure point in your application. How are microservices going to handle that? By horizontal scaling perhaps?
What irks me the most is that post feels like a choose a side and stick with it scenario. Like all things in life there are a lot of grays between white and black.
I understand you can't address all the things. And you did address some of them. But because of those sharp lines the post feels more like an ad than a genuine expression of information.
Hey @xwero! Super thanks for the feedback!
And, to be fair, that was a really unexpected feedback, because, my general idea I was going for was totally the opposite (lean towards Monoliths, even more in the case you are not sure, -- since Microservices can be really hard, complex and a total overkill in some scenarios).
I'll try to reference some examples below of me leaning to monoliths:
Or, in the comparison table, I specifically put the term really large to emphasize that microservices can be a overkill for most apps:
So yeah, if you got the sense that the article leans heavily towards microservices, I'll look into editing it a little bit to make it even more explicit that the opposite is true hahahah.
Regarding your point about horizontal scaling: You’re absolutely right that horizontal scaling—where different servers run the same application—is a valid strategy for monoliths. I agree that I could provide more context on this alongside the discussion of vertical scaling to give a more balanced view of scaling approaches in monolithic architectures.That said, scaling a monolith with tightly coupled components often introduces challenges that are different from scaling individual microservices -- which was the vibe I was going for. I'll definitely explore that further in a revision.
Regarding this part of your comment:
As with the leaning to the microservices, the opposite is what I was trying to go for. I even mention that you can convert one into the other and a few ways on converting, e.g.:
But, on the revision, I'll try to emphasize more this gray area! Thanks for noticing!
And with the last part, that this feels more like an ad instead of a genuine piece, I’m sorry if the article felt more like an ad—that wasn’t my intention. My primary goal is to provide valuable and practical insights, and I work hard to strike a balance between highlighting the brand and delivering genuine, helpful content. I’ll make sure future pieces keep this balance even sharper.
Thanks again for your valuable input—I’ll be reviewing the article with your points in mind. If you have any specific examples of where you think the balance could improve, I’d love to hear them!
I think multiple posts of the Brownfield replacement process would be better than this one monolith versus microservices post.
It will allow you to provide more information about the path to go from a single server to a full microservice solution.
The pressure point is not always with the code. The title says it is 101, which means people are maybe not aware of having the application and the database on the same server can become a problem.
You provided a lot of information, but some of the things will be overlooked because you added as what can be considered as a side-note like modular monolith and DDD. It is easy to discard a single sentence as something that is not that important.
I'm all over the place, but i think you can pick up some of the things.
Great Article 👏
Thanks a lot @petermwambi!
Hi Lucas,
Very nice and helpful !
Thanks for sharing.
Hey @jangelodev!
Thanks a lot! Glad that I could help another 🇧🇷
See ya!
Thanks a lot 👍
Is it true that in a Microservice architecture, each service is a monolith itself?
Hey @ali_mirzaei_3baf003de70dc! Really great comment! This is a super common analogy and it can be in parts true (but it also can be in parts false).
Here's my take on that:
If you think that a microservice usually is deployed with everything it needs to work, it can look similar to multiple monoliths, since, you're deploying multiple things, that contains databases and all the other things they need to run -- specially if the microservice is BIG (which generally is a bad practice, since they usually should be used within the same domain).
But as I mentioned, that analogy is not 100% correct. Although you could say each microservice has a "monolithic structure" in terms of its independence and internal organization, it's the distribution and decoupling of services that make a microservice architecture different from a traditional monolith.
Thanks a lot and feel free to leave any more questions!
Thank you for this,I want to migrate my backend monolith app to microservices. How do I do it. Stack is AWS offerings,fatapi, postgreSQL,google vision and redis
Hey! Thanks for the comment @adesoji1!
Migrating things is certainly a challenge! Although it's impossible for me to help in terms of precisely how to solve it, feel free to use the guides and ideas mentioned on this article as a path towards your goal (Strangler Fig might be the one you're looking for the most ;))
Thank you for the blog post. I heard good things of Hono.js and want to look at it today.