Introduction to Scalable Software
This is the first article on how I believe an application should start and grow, based on:
- How much I studied the subject
- My experience applying in my own business in the past
- The day-to-day working in startups was applying and evangelizing the - - concepts I will address.
First, I will talk about common problems caused by decentralized systems and give an overview of what we will discuss in the following articles.
It's a pervasive topic that can barely fit in a book, so I'll try to categorize the contents and apply the concepts in real, live projects, which I'll publish on my Github.
A Common Story Among Devs
Every beginning dev learns to build one application at a time, like simple monoliths.
Advancing their studies, beginners discover the world of microservices and how large applications behave.
At this point, devs believe that every good application should be split into microservices, either because breaking a monolith later is difficult or because microservices are more "performative", "more concise", and "more independent", etc.
So, in the first experience creating microservices, some problems will happen:
- You find a service communicating synchronously with another, and you realize that they are highly dependent, and it - would be much easier if both were together.
- You start thinking about where you should write your next feature and how it will communicate with other services. (My - God, is this supposed to be a new microservice???)
- The application starts to have performance problems.
- With more microservices, troubleshooting the entire application is more challenging.
- One service crashes and others start throwing errors.
- You start to miss the monoliths.
- You wonder how all this happened.
- You cry
I could list several problems and disasters caused by decentralizing an application, but I want to focus on how these problems happen and how to avoid them.
The Documented Business
It's common to see developers just getting their hands on the code and starting troubleshooting, not knowing they could be creating other huge problems.
Before starting to program, a lot of business documentation is needed. The first prerequisites are:
- The business model is documented by business experts, such as product owners, product managers or similar positions, describing in a language that everyone understands how each process should occur.
- Domain diagrammed according to the business documentation (I suggest using Event Storming)
With business documentation and domain modelling, it is easy for any developer, even newly hired, to understand how the business works just by looking at a diagram.
I will discuss business documentation in the following article and reference other dedicated articles.
With the business documented and diagrammed, we can now take another step towards code, but we need to discuss architecture first.
I will discuss business documentation in the following article and reference other dedicated articles.
With the business documented and diagrammed, we can now take another step towards code, but we need to discuss architecture first.
The Software Architecture
The domain diagram brings us clarity about possible microservices architectures.
But that doesn't mean we should go for a microservices architecture.
Depending on the company's size, when you don't expect to have many users and/or a small developer team, it makes much more sense to start with a monolith.
Which?? Start with a monolith?? Yes, with fewer resources, the priority is to create software easy to maintain, debug and deploy.
Contrary to many beliefs, it is likely that the best way to start the software is through a monolith.
Keep in mind that the architecture must be consistent with the size of the business. The system will scream at you when it's time to separate a feature into microservices. The reasons are diverse:
- A feature consumes too much resource, and the whole monolith is scaling because of a small piece of code.
- Your database is overloaded due to some functionality, and you need to isolate this operation in another database.
- The application has started to be massively used, and it makes sense to create worker instances to handle asynchronous processing.
With a single code base and a single deployment, it's easier to track bugs, monitor the application end-to-end, and create an easy-to-maintain CI/CD flow. Furthermore, the trend is for infrastructure costs to be much lower than using a monolith.
Soon I will be writing about monoliths and creating from scratch live and documenting the process of creating a video streaming system built to scale, so I can demonstrate all the concepts mentioned in an actual project.
Starting a monolith brings us some risks. If the design is not for scalability, it will be challenging to migrate a monolith to a microservices-based architecture.
The Software Design
The problem with a monolith usually is that refactoring becomes extremely difficult when it comes time to split the application.
However, it is possible to model the monolith so that the impact of refactoring is minimal.
I experienced this process in my old betting automation company's system. It was possible to split a monolith into 4 microservices in just 2 days.
To make such refactoring possible, we must apply many concepts of Clean Code and Domain Driven Design.
It is impossible to be a purist in all applied concepts since many constantly contradict each other.
As with any software concept, the most important thing is to take advantage of what makes sense for you, your team and your project.
Absorb what adds you, discard what doesn't apply and adapt to your reality.
In the following article, I will talk about the heart of scalable software, and this time we're going to get our hands on the code.