the starting point
If there is one thing few courses teach and many companies hide, it is the path a system takes to reach production. It sounds trivial, but believe me: I have met senior developers who never had the experience of running a deploy. That happens because in large companies today it is common to have extremely bureaucratic processes and automated tooling that take care of it.
But what happens when you step outside that environment and need to put a system online by yourself? Before talking about scalability, we need to understand what it means to take a system to production professionally. That includes the basics, from how the internet, servers, DNS and hosting work, all the way to more complex questions such as CI/CD strategies and monitoring.
And here is an important point: before scaling, a system needs to exist.
For a long time, systems were built in simpler ways, without much concern for growth. With the rising demand for digital transformation, that changed abruptly.
The most common model used to be the monolith: a single application running on a single server, serving every request, often sharing resources with the database itself. For a small number of users that worked well, and scaling was a matter of adding more processing power, what we call vertical scaling. But does that approach hold up when we are talking about thousands or millions of requests?
That ended up being the reality of many systems for years, and it is still a valid model when properly sized. However, as demand grows, challenges appear that have to be solved for the system to keep running efficiently, since powerful hardware is expensive and using a machine's resources efficiently is a challenge in itself.
monoliths and the false urgency of microservices
For a long time, systems were built following the MVC (Model-View-Controller) model with technologies like .NET, Java and PHP. These systems usually ran on a single machine, where all the business logic, user sessions and database connections were centralised.
Scaling a monolith required a different kind of thinking: how do you distribute user sessions? How do you avoid bottlenecks in the database? How do you reduce load on the server? The answer involved handling connections more carefully, storing user sessions in NoSQL systems with faster reads, and introducing caching to reduce direct database access. It was hard work, but still possible.
Imagine your system has thousands of users logged in simultaneously, and each one needs to keep an active session on the server.
If those sessions are stored only in local memory, every new application instance created to absorb demand loses that information. This is one of the most common challenges when scaling a monolith, and solutions like Redis help keep sessions consistent across multiple instances.
Today, with the convenience of the cloud and cloud native strategies in many companies, that problem no longer exists. Scalable infrastructure is one click away, and that led many companies to spend far more than necessary. Instead of optimising a monolithic system to support higher volume, many teams fall into the trap of jumping straight to microservices without validating the real need first.
This is one of the biggest mistakes when it comes to scalability. The cloud brought an enormous technological leap and a lot of convenience, but without good planning the cost can scale just as much as the system. Splitting a system into microservices without proper sizing can create unnecessary complexity, make maintenance harder and increase costs with no real performance gain. Before any decision, it is essential to know how to run load tests on the system and understand how to optimise it without losing efficiency.
On top of that, distributed systems bring new challenges, such as cache invalidation and eventual consistency problems: multiple services may be serving stale data because they cannot invalidate caches correctly across instances, or because several systems are inserting and updating data that another one needs at the same time. This has to be considered in the design of the application.
Investing time in optimising a monolith before breaking services apart can save thousands of dollars in infrastructure. Sizing the system correctly and monitoring how it behaves are fundamental steps to making sure scalability happens sustainably.
the common mistake in adopting microservices
Many companies take inspiration from success stories like Netflix, Uber and Amazon to justify adopting microservices, but ignore the complexity those companies face to reach millions of requests in distributed systems. Talks like Netflix's Mastering Chaos show that operating at that level requires much more than just splitting a system: it demands governance, automation, deep technical capability and a strong DevOps culture.
Without those prerequisites, what ends up being produced in the market is poorly modularised monoliths, badly distributed services, and contexts simply bolted onto the system with no prior technical vision. Mandates about using microservices get implemented without understanding the business requirements, resulting in systems that are hard to maintain, evolve and scale.
Adopting microservices also requires a shift in the company's mindset. To make it work you need to build a solid culture of DevOps and systems architecture, ensuring there is CI/CD, automated testing, control over the infrastructure and a damage mitigation strategy. Without those pillars, the company risks replacing a monolith that is hard to scale with a chaotic set of disconnected services.
Building efficient scalability goes far beyond choosing between monoliths and microservices. What matters is being aware of the impact of each decision and making sure there is planning and control to avoid structural problems later on.
adopting the 12 factors
A solid approach to guide the construction of scalable, well-designed systems is to follow the twelve-factor app methodology written by Adam Wiggins. These principles establish good practices for developing modern applications, ensuring they are portable, resilient and easy to maintain.
The 12 factors cover everything from dependency and configuration management to deployment practices, scalability and structured logs. Companies that adopt these principles from the start build systems that are easier to operate and less prone to unexpected failures.