Home / Courses / Scalability for Beginners / I — Core Concepts
I — Core Concepts
Article 1 of 9

Why Do Applications Stop Scaling? Understanding Bottlenecks Before Fixing Them

The common bottlenecks that make applications stop scaling, the difference between vertical and horizontal scaling, and why "measure first, then optimize" is the guiding principle throughout this series.

July 10, 2026

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:

  • Not distinguishing CPU-bound from I/O-bound work. Computer work broadly splits into two kinds: work that spends time on the CPU (heavy computation, compression, encoding), and work that spends time WAITING (database queries, external API calls, reading/writing files). The solutions for each are completely different — adding more CPU doesn't help if the bottleneck is I/O, and vice versa. Misdiagnosing this makes scaling efforts pointless.
  • Single point of failure. One application instance, one database, no backup. The moment that resource fills up or goes down, the entire system goes down with it — there's no way to redistribute the load elsewhere.
  • Vertical scaling has a ceiling. Upgrading to a bigger server (more CPU/RAM) is the fastest fix, but there's a hardware ceiling you can buy your way to, prices don't scale linearly (a server twice as powerful is often priced at more than twice the cost), and it usually requires downtime during the upgrade.
  • A resource assumed to be shareable turns out to be locked. A concrete example: SQLite (which we used in the previous FastAPI series) locks the entire database file during a write operation — great for a small single-user app, but a serious bottleneck the moment there are many concurrent requests that need to write data.
  • Optimization done by guessing, not data. A team rushes to add a cache in the wrong place, or upgrades the server when the actual bottleneck is an unindexed database query. Without measurement, scaling efforts easily miss the target — this is covered in full in Part 3.
  • 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 worksUpgrade one machine: more CPU, RAM, diskAdd more machines/instances running in parallel
    Implementation complexityLow — just upgradeHigher — needs a load balancer, correctly shared state
    Maximum limitHits a hardware ceilingTheoretically near-limitless
    Downtime during upgradeUsually needs a restart/downtimeCan be done with no downtime (add a new instance, retire the old one gradually)
    Weak pointStill a single point of failureNeeds the application to be designed for it (stateless)
    These two strategies aren't mutually exclusive — most production systems use both: each instance gets vertically scaled to a sensible size (not under-provisioned), then horizontally scaled to handle the total load and avoid a single point of failure. We'll get hands-on with horizontal scaling in Part 7, using the 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:

  • Response time rises significantly as traffic grows, even after the code and queries are already optimized.
  • Resources (CPU, memory, database connections) are consistently near their maximum limit, not just occasionally during spikes.
  • There's a business requirement for high availability — the system must never go down, even during maintenance.
  • 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.

    Summary

  • Scalability = adding resources proportionally to handle rising load, without a significant drop in performance.
  • Common bottlenecks: not distinguishing CPU-bound from I/O-bound, single points of failure, the vertical scaling ceiling, resources that turn out to be locked, and optimizing without data.
  • Vertical scaling (upgrading one machine) is simpler but has a ceiling; horizontal scaling (adding more instances) is more complex but far more scalable.
  • Don't scale before you actually need to — extra complexity has a real cost.
  • Topics

    ScalabilityFundamentals