Fundamentals
The canonical scaling path
The usual sequence in which a successful web app adds parts, from one server to queues, shards and regions, with the symptom that triggers each step.
Most successful web products follow the same path. Each step is triggered by a specific symptom and adds complexity. Take a step only when its symptom shows up.
The big idea
The path is a ladder of bottlenecks. Each rung solves the bottleneck that the previous rung exposed. Teams get into trouble by jumping to the top rung, with microservices, sharding and a streaming platform, while they still have the scale of the second rung.
Walking through it
- One server. The app and database share one box. This is fine for a prototype and often for the first thousands of users. It ends when the two compete for CPU and memory, or when a deploy takes everything down.
- Separate the database. Move it to its own machine or a managed service. Each can now be sized on its own. It ends when one app server cannot handle the traffic, or when you cannot deploy without downtime.
- Load balancer and several stateless app servers. This needs the work in stateless services. You get zero-downtime deploys and survive a node failure. It ends when the database becomes the bottleneck, usually on reads.
- Cache, read replicas and a CDN. A cache absorbs hot reads. Read replicas take the rest. A CDN serves static files and media from the edge. Many read-heavy systems grow a long way here. The new problems are cache invalidation and replica lag, where users do not see their own writes.
- Queues, sharding and regions. Queues move slow work off the request path. Sharding splits data once one primary cannot take the writes. Multi-region deployments cut latency and survive a region outage. These are the expensive steps, and each one adds failure modes.
The stage 5 architecture looks like this:
Important
Each step is cheaper and less risky than the next one. Instagram had a small engineering team for its first years and grew to tens of millions of users on Django, Postgres, Redis and Memcached. It sharded Postgres only when it had to.
Common mistakes
- Jumping to stage 5 early. Sharding and microservices at stage 2 scale add cost with no benefit.
- Skipping stateless work. Without it, stage 3 cannot happen.
- Adding a step without a symptom. Write down the metric that justifies each step.
Check yourself
-
What symptom usually ends stage 3?
Answer: the database becomes the bottleneck, usually on reads.
-
Which step should come before sharding, and why?
Answer: a cache and read replicas. They are cheaper and reversible, and many read-heavy systems grow far with them.
Key takeaways
- Each stage of the path is triggered by a symptom, so measure before you add a part.
- The order is: separate the database, make app servers stateless, add cache and replicas, then queues, shards and regions.
- The first three stages cover most products for a long time.
Further learning
This AWS re:Invent talk walks through almost exactly this evolution, from one instance to a multi-tier architecture serving 10 million users, with the reasoning for each step:
Instagram's engineers describe how they scaled out, scaled up and scaled the team. It is a useful real-world companion to the stages above:
Next, see the three independent ways to split a system, in the scale cube.
Related
Scaling fundamentals
Vertical versus horizontal scaling, stateless services, the usual order in which a growing system adds parts, and how to find the real bottleneck. Start here for the scaling map.
Growing a marketplace
A worked plan for a small marketplace that expects 10 times its traffic in a year, step by step with real numbers, and why it needs no sharding.
Replication
Keeping copies of the same data on several machines, the three topologies that databases use, and the anomalies that replication lag causes. Start here for the replication map.
Sharding and partitioning
Split data across machines by choosing a shard key, hashing or ranging it, routing requests, handling hot spots, resharding without downtime and generating IDs that stay unique.
Multi-region architecture
Active-passive, active-active and cell-based designs for latency, disaster tolerance and data residency, with the recovery, consistency and cost trade-offs each one carries.