Scalability: When Should We Care About It?
Part Four of the Series: Building the Right Software Systems
When a new team starts building a system, an early question often appears: Will the system be scalable? The question itself is a good one. The problem begins when we misunderstand what Scalability actually means. Some teams start with a few hundred users, then design their architecture from day one to support tens of millions.
- They use Microservices.
- They add Message Queues.
- They build Distributed Systems.
- They introduce Kubernetes.
- They put a Cache everywhere.
Then, months later, they discover that the system is extremely complicated while the number of users has barely changed. On the other hand, some teams postpone thinking about scalability until the system is under real pressure. By then, changing the design can be extremely expensive.
So, when should we care about scalability? The answer is not: "From the beginning". And it is not: "When we need it". The better answer is: Think about scalability early, but don't build complexity early.
What Does Scalability Actually Mean?
When some people hear the word Scalability, they immediately think about the number of users. But scalability is broader than that. A system may need to scale because of:
- An increasing number of users
- An increasing amount of data
- An increasing number of requests
- An increasing number of developers
- An increasing number of features
- An increasing number of customers
- Or even an increasing number of teams working on the system
So we can think about two different types of scalability.
Technical Scalability
Can the system handle more data, requests, and users?
Organizational Scalability
Can the system continue evolving as the team and project grow?
The second is often overlooked. Imagine a system that can handle one million users, but adding a small feature requires modifying ten different parts of the code. Is that system truly scalable? Technically, perhaps. From an engineering perspective? Not really.
Don't Build What You Don't Need
Let's say we have a new application with 1,000 users. The system needs a database, an API, and some background processing. We could build the system in a simple and clear way. Instead, the team decides to start with:
- Multiple Microservices
- Kubernetes
- An Event Bus
- Distributed Cache
- Service Discovery
- Multiple databases
- A complex monitoring system
All of this is done "in preparation for the future". But there's a problem. The future we designed for hasn't arrived yet. Meanwhile, feature development has become harder, operating the system has become more expensive, debugging has become more difficult, and a new developer now needs to understand dozens of components before they can modify a simple feature. We have turned a potential future problem into a real problem today.
Complexity Has a Cost
Every architectural decision has a price. When you add a new service, you're not just adding code. You're also adding:
- A new deployment process
- New monitoring
- New logs
- New failure scenarios
- Network calls
- Authentication or authorization
- Error-handling mechanisms
- And possibly an additional team or specialized knowledge to manage it
This doesn't mean Microservices are bad. It means they should have a reason to exist. If the problem doesn't require them, they become a cost without providing real value.
"We Can Scale Later" Isn't Always the Right Answer
On the other side, there's another dangerous idea: "We don't need to think about scalability now. We'll solve it when the problem happens". Sometimes this is perfectly reasonable. But not always. Some architectural decisions are difficult to change later.
For example, if you design the entire system around a particular way of storing data and eventually have millions of records, changing that design may no longer be a simple task. Or if the entire system assumes that a particular operation happens synchronously, converting it to an asynchronous process later may be significantly more complicated. So there is an important difference between: Not building the solution now
and Not thinking about the problem now. We should think about the future, but we don't need to build everything for it.
Design So You Can Scale
This is perhaps the most important idea in this article. The goal isn't to make the system capable of massive scale from day one. The goal is to make the design capable of evolving when the need arises. For example:
- Clear boundaries between system components
- Low coupling between different parts
- A logically designed database
- Clear APIs
- Avoiding unnecessary dependence on a single technology
- The ability to improve components that become bottlenecks later
In other words: Build for change, not for imaginary scale.
Start with a Monolith If It Makes Sense
There is a common belief that a professional system should start as Microservices. But a Monolith is not a flaw. For many projects, a Monolith can be the better choice at the beginning. Not because we don't care about scalability, but because we want to reduce complexity while we gain a better understanding of the system.
You can have a well-organized Monolith divided into clear Domains, and later separate some of its parts when a real need appears. That's much better than building ten independent services before you even know where the boundaries of the system should be.
When Do We Actually Need to Scale?
There is no magic number. It isn't true that: "When we reach one million users, we must use Microservices". Nor is it true that: "When we reach 100,000 requests per minute, we must do X". Numbers matter, but they aren't the only factor. Ask: Where is the actual problem?
- Has the database become a bottleneck?
- Is a particular API receiving a huge number of requests?
- Is a particular operation consuming a significant amount of CPU?
- Do we have long-running operations affecting user response times?
- Does a particular part of the system need to scale independently?
These questions are more important than the number of users alone.
Measure Before You Optimize
One of the worst habits in systems engineering is optimizing something without proving that it is actually a problem. Someone says: "We should add Redis". Why? "Because caching will make the system faster." Maybe!
But do we know where the slowdown is? Is the database the problem? Is the query inefficient? Is there a network issue? Is the application itself spending too much time processing? Without measurement, we're guessing. Good engineering doesn't rely on guesses when we can collect data.
Performance Is Not Scalability
There is an important distinction between these two concepts. A system may be extremely fast with 100 users but unable to handle 100,000 users. A system may also be capable of handling a large number of users while still having unacceptable response times for certain operations. Performance is about how efficiently a system operates. Scalability is about its ability to handle increasing load. The two are related, but they are not the same thing.
Don't Forget the Cost of Scaling
We might be able to make a system handle ten times as many users. But the important question is: How much will that cost us? If supporting a small increase in usage requires ten times the infrastructure, we may have a design problem. Good scalability doesn't simply mean that the system can handle more. It means that the cost of growth remains reasonable. This is where good design, measurement, and choosing the right solution for the actual problem become important.
When Does the Current Architecture Become Insufficient?
You might start with a very simple system. Then the project grows. At some point, certain problems begin to appear:
- A particular component needs significantly more resources than the rest of the system.
- Some operations have become slow.
- A particular team needs to develop independently.
- Deploying the entire system to change one small part has become expensive.
- The database has become a bottleneck.
- Background processes have started affecting the user experience.
These are important signals. This is when you can start separating certain components or introducing additional technologies. Not because: "Microservices are the modern way". But because: The problem has become worth the cost of the solution.
Growth Should Be Gradual
A good system doesn't need to know the future. It needs to be able to respond to it. You might start with:
Monolith → Modular Monolith → Some asynchronous operations → Database optimization → Cache → Separate a specific service → Perhaps Microservices later.
You don't necessarily need to go through all of these stages. You may never need some of them at all. The point is that every step should happen because of a real problem—not because we're afraid of a problem that might never happen.
Think About "Where Do We Want to Be?"
Before choosing any technology for scaling, try to understand the expected shape of growth. Is the project:
- An internal application for a small team?
- A SaaS product?
- An e-commerce platform?
- A financial system?
- A content platform?
- A real-time system?
- An API consumed by other companies?
The nature of the system determines the types of challenges that will appear. An internal accounting system is not the same as a video platform. A booking platform is not the same as a search engine. There is no single architecture that works for everyone.
Scalability Is Not Just a Technical Problem
There is a deeper point here. Sometimes the problem isn't the system at all.
Suppose we have one million users, but the business process itself doesn't scale. Adding more servers won't solve the problem. We may need to change the process, automate it, divide it into smaller parts, or remove an entire step.
A good engineer doesn't only ask: "How can I make the system handle more?" They also ask: "Is this actually the right way to perform the work?"
Principles to Remember
When thinking about scalability, remember:
- Don't build infrastructure for a problem that doesn't exist.
- Don't ignore potential future problems.
- Design the system so it can change.
- Measure before you optimize.
- Don't use Microservices simply because they are popular.
- Don't make the database the center of every design decision.
- Think about the scalability of the team, not just the servers.
- Make every scaling step a response to a real need.
- Simplicity in the beginning is not weakness.
- And complexity is not proof of professionalism.
Conclusion
Scalability isn't about building the largest possible system from day one. Nor is it about ignoring the future until a problem appears. The better approach lies somewhere in the middle: Understand how the system might grow, then design it so you can evolve it when that growth arrives—without paying today for complexity you don't need. We cannot know the future with certainty. But we can build systems capable of adapting to it. And that is the real goal of Scalability.
In the next article, we'll move to one of the most important parts of any system: data. We'll discuss why the database should be treated as part of the engineering design—not simply a place where we put tables—and how seemingly simple data-design decisions can shape the future of an entire system.



