Real-world system design
How Instagram scales, from one server to a billion users
How a photo-sharing app grows from one server to hundreds of millions of users — told through Instagram's public engineering talks, in AWS terms.
Play it — turn the traffic up yourselfStage 1 of 6
Launch (~5K users)
- Mobile appMobile application
- EC2Amazon EC2
- RDSAmazon RDS
What breaks
Your single app server is over capacity — every request, and every photo upload, is queueing behind one machine.
One EC2 instance is both a single point of throughput and a single point of failure. Every page load, API call and photo upload runs through it, so the moment traffic outgrows one machine's CPU everything slows at once — and if that box dies, the whole site is down. There is nowhere for the load to go.
The fix
A load balancer lets you run a group of identical app servers instead of one, spreading traffic across them — and a single failing box no longer takes the site down. Moving photos to S3 behind CloudFront takes the heaviest bytes off the servers entirely: they serve from the edge, near the user, instead of from your one machine's disk.
Serve large static files from object storage and a CDN, not from your app server — and never run on a single machine.
Based on: Scaling Instagram (Instagram, 2012)
Stage 2 of 6
Traction (~100K users)
- Mobile appMobile application
- CloudFrontAmazon CloudFront
- S3Amazon S3
- ALBApplication Load Balancer
- EC2 Auto ScalingEC2 Auto Scaling Group
- RDSAmazon RDS
What breaks
Every feed load hits Postgres, and the single database is saturating on reads while the app tier still has room.
You can add app servers all day, but they all read from one Postgres. Feeds, profiles and timelines are read far more often than they are written, so reads pile up on the primary first — it becomes the bottleneck the app tier no longer is. A bigger database instance buys time, not a solution.
The fix
A cache keeps the hottest feeds in memory, so the great majority of reads are answered without touching Postgres at all — and a read replica serves the queries that get through from a second copy. Reads now scale sideways by adding cache and replicas, leaving the primary free to handle the writes.
Reads scale with a replica and a cache long before writes ever need to.
Based on: Scaling Instagram (Instagram, 2012)
Stage 3 of 6
Popular (~1M users)
- Mobile appMobile application
- CloudFrontAmazon CloudFront
- S3Amazon S3
- ALBApplication Load Balancer
- EC2 Auto ScalingEC2 Auto Scaling Group
- ElastiCache RedisAmazon ElastiCache for Redis
- RDSAmazon RDS
What breaks
The database is fine now, but the app servers build every user's feed on the request — and that work is saturating the fleet.
Building a feed means gathering everyone a user follows and merging their recent posts — real CPU work, done while the user waits. At a million users, that work multiplied by every app open saturates the web tier even though the database is cached. The request path is doing heavy work that does not need to happen while someone is waiting for a response.
The fix
A queue lets the app hand off feed-building and return to the user immediately, while a separate fleet of workers does the heavy merge in the background and writes the finished feed to the cache. The request path is fast again, and you scale the workers independently of the web tier — each grows only as much as its own load needs.
When work can wait a second, take it off the request with a queue and background workers.
Based on: Scaling Instagram (Instagram, 2012)
Stage 4 of 6
Scale (~10M users)
- Mobile appMobile application
- CloudFrontAmazon CloudFront
- S3Amazon S3
- ALBApplication Load Balancer
- EC2 Auto ScalingEC2 Auto Scaling Group
- ElastiCache RedisAmazon ElastiCache for Redis
- RDSAmazon RDS
- SQSAmazon SQS
What breaks
Reads are handled by the replica and the cache, but every write still lands on one Postgres primary — and that single machine is now the wall.
Replicas scale reads, not writes — every new post, like and follow must still be written to the one primary, and a bigger machine only buys you so much. Vertical scaling has a ceiling, and at ten million users you hit it: one database can no longer hold the write throughput, nor, before long, the data itself.
The fix
Sharding splits the data across many databases, each holding a slice of the users, so writes spread out instead of stacking on one primary — four shards take roughly a quarter of the writes each, and you add more as you grow. The catch is identity: a row's id must be unique across every shard, which is why sharding comes with a global id scheme. Instagram baked a timestamp, a shard number and a per-shard sequence into each id, so ids never collide and still sort by time.
Past one machine's write capacity you shard — and sharding needs ids that never collide across shards.
Based on: Sharding & IDs at Instagram (Instagram Engineering, 2012)
Stage 5 of 6
Global (~100M+ users)
- Mobile appMobile application
- CloudFrontAmazon CloudFront
- S3Amazon S3
- ALBApplication Load Balancer
- EC2 Auto ScalingEC2 Auto Scaling Group
- ElastiCache RedisAmazon ElastiCache for Redis
- DynamoDBAmazon DynamoDB
- SQSAmazon SQS
- AuroraAmazon Aurora
What breaks
One region now serves the entire planet — the app tier is stretched, and every user outside it waits on a round-trip across the ocean.
A single region hits two ceilings at once: the app fleet can only grow so far, and a user in Asia reaching servers in the US pays hundreds of milliseconds of latency on every request. Scaling up in one place buys capacity, but it cannot fix distance.
The fix
Geographic routing sends each user to the region closest to them, so requests are served near home and the load splits across regions instead of stacking on one. Instagram runs a separate cluster per continent — European data in Europe, US data in the US — and migrates a user's data if they move continent for good. Latency drops, and each region carries only its own share.
At global scale, distance is the bottleneck too: you run a copy of the whole system in each region and route users to the nearest one.
Based on: Instagram: from Redis to Cassandra (High Scalability, 2013)
Stage 6 of 6
Planet scale (~1B users)
- Mobile appMobile application
- CloudFrontAmazon CloudFront
- S3Amazon S3
- Route 53Amazon Route 53
- ALBApplication Load Balancer
- EC2 Auto ScalingEC2 Auto Scaling Group
- ElastiCache RedisAmazon ElastiCache for Redis
- DynamoDBAmazon DynamoDB
A planet-scale system is really many regional systems behind geo-routing — each continent served close to home, with the data that follows the user.
Based on: Instagram: from Redis to Cassandra (High Scalability, 2013)
Now try it yourself
Reading is one thing. Turn the traffic up on Instagram's architecture, watch it break, fix it — then build the whole thing from a blank canvas.
Play the scale journey