Picture the task-tracker-api you built in the FastAPI for Beginners series suddenly going viral — a startup adopts it for their whole team, then another team follows suit. Within a month, traffic goes from a few dozen requests a day to thousands per minute. At first everything's fine. Then response time starts creeping up from 50ms to 2 seconds. Then timeout errors start appearing. Then the server starts restarting on its own because it's out of memory.
Panicking, you immediately upgrade the server to the highest spec available. The problem disappears for a while — until traffic climbs again and the same problem reappears, this time with a much bigger cloud bill. This is an extremely common pattern: throwing more resources at a problem without understanding why the system stopped scaling in the first place.
This article digs into the root of the problem: what bottlenecks make applications stop scaling, and two basic strategies for dealing with them.
What Is Scalability?
Scalability is a system's ability to handle increasing workload (traffic, data volume, number of users) by adding resources proportionally, without a significant drop in performance. The key word is "proportionally" — a scalable system, if traffic doubles, only needs a reasonable amount of extra resources to stay responsive. A system that isn't scalable sees its performance collapse much faster than traffic grows, or needs resources to grow far more than 2x just to keep up.
Common Bottlenecks That Make Applications Stop Scaling
Before we can fix a scaling problem, it's worth understanding where bottlenecks typically show up:
Vertical Scaling vs. Horizontal Scaling
Once you know where the bottleneck is, there are two basic strategies for adding capacity:
| Vertical Scaling (scale up) | Horizontal Scaling (scale out) | |
|---|---|---|
| How it works | Upgrade one machine: more CPU, RAM, disk | Add more machines/instances running in parallel |
| Implementation complexity | Low — just upgrade | Higher — needs a load balancer, correctly shared state |
| Maximum limit | Hits a hardware ceiling | Theoretically near-limitless |
| Downtime during upgrade | Usually needs a restart/downtime | Can be done with no downtime (add a new instance, retire the old one gradually) |
| Weak point | Still a single point of failure | Needs the application to be designed for it (stateless) |
task-tracker-api we already have.
When Do You Actually Need Scaling?
One important thing that's often overlooked: don't scale before you actually need to. Adding complexity (many instances, a caching layer, a distributed database) has a cost — harder to debug, more things that can break, and extra maintenance effort. For an app with small-to-medium traffic, a single reasonably powerful server is often more than enough for years.
Signs you're genuinely starting to need a more serious scaling strategy:
The principle we'll hold onto throughout this series: measure first, then optimize — not optimizing based on intuition or copying a blog post about large-scale architecture that may not even be relevant to the scale of your own problem.