One app · nine stages · 50 users to 50 million

Scaling PhotoApp

Every box in a system diagram is there because something broke. Step through the build and watch each one break: the load balancer, the session store, the index, the cache, the replicas, the shards — each arriving the moment the app can no longer live without it.

Stages
9
Feed budget
200 ms
Cache hit / db read
0.8 / 26 ms
Benches
3 interactive

The build

Nine stages, each triggered by a failure

Nobody asks for a cache. Users ask for a fast app. Read each stage as a chain: something breaks, you add a component, and the component hands you a new problem. The rail is a real sequence — you cannot get to shards before you have run out of one machine.

← → to step

What broke

What we added

What it costs

Trace a request

Where the milliseconds actually go

The finished topology, one request at a time. Reads and writes take different paths on purpose: the feed is optimised down to a single millisecond of memory lookup, while the upload is allowed to take a second and a half because uploading feels like work.

Request tracer

Stage 08 topology

    0 ms0.0 ms200 ms budget

    Pick a scenario and run it.

    Cache bench

    Hit, miss, evict, go stale

    Four slots, eight photos, least-recently-used eviction. Request photos by hand or fire a realistic burst where a handful of celebrity posts soak up most of the traffic. Then edit a cached bio and watch the cache confidently serve the old one — the failure mode that is far worse than an empty cache.

    Redis, capacity 4, LRU

    Cache slots

    Request a photo

    Tape

    Consistency drill

    The database and the cache now hold the same row twice. Sooner or later they disagree.

    Freshness policy — industry-acceptable defaults
    DataPolicyWhy
    Home feedTTL 30 sA few seconds of staleness is invisible while scrolling.
    Trending listTTL 60 sRecomputed constantly, wrong by a rank nobody notices.
    Profile cardTTL minutesSmall, read constantly, changes almost never.
    Follower countTTL 60 s41 instead of 45 for a minute costs nothing.
    Privacy & permissionsno TTL — invalidateStale here means showing private photos to the wrong person.

    Shard bench

    Why adding one machine can move all your data

    Thirty-six user IDs spread across shards. With plain user_id % N, adding one shard rewrites the rule for almost everybody — billions of rows would have to physically move. Switch the strategy and add a shard again: consistent hashing takes a slice from one neighbour and leaves the rest alone.

    Shard mapper

    4 shards

    Add or remove a shard to see how much data has to move.

    Keys · shard assignment

    Load per shard

    Before you draw a single box

    Altitude, requirements, shape

    High-level design

    The zoomed-out blueprint

    Big pieces and the path between them: app servers, database, cache, queue, CDN. Where does a request go, where does data live, what breaks first when traffic grows.

    • “Design Instagram.”
    • “Design a photo-sharing app.”

    Graded on: data flow, component choice, and whether you can name the cost of each choice.

    Low-level design

    The inside of one box

    One feature, in code. What happens on tap, which function handles it, how you avoid counting the same user twice, which classes and data structures hold it.

    • “Design the like button.”
    • “Design an in-memory cache.”

    Graded on: objects, data structures, edge cases. No servers required.

    Say your altitude out loud, in the first sentence

    “I’ll stay at the high level — components, data flow and trade-offs — and we can zoom into any one of them.” Interviewers rarely stop you when you answer at the wrong height; they just let you spend twenty minutes there. Mismatched altitude is one of the most common ways strong candidates lose.

    The five questions · ask these before you design anything

    Functional or non-functional?

    0 / 8

    A feature you can point at and test is functional. A quality everybody feels but nobody can point at — speed, durability, scale, availability, cost — is non-functional. Two apps with identical feature lists can be completely different systems.

    One codebase, one deployment

    Sign-up, upload, feed, likes and comments all live in one program and call each other with plain function calls. No network in the middle, nothing in the middle to fail.

    • One thing to deploy, one thing to test, one log to read
    • A small team moves fast because there is less to hold in your head
    • Correct for PhotoApp today, at a few thousand users

    Where it starts to hurt

    You cannot scale one part on its own. The feed needs ten servers and uploads need two, but you scale the whole program to ten either way — and you pay for eight servers of upload capacity nobody asked for.

    Change the sign-up page and you redeploy everything, including the feed.

    The interview room

    Seven prompts · tap to see the answer that scores

    The pattern in every one of these: name the cause, give the fix, then volunteer the wrong answer and why it is wrong. Bringing up the failure before the interviewer asks is what separates “knows the feature” from “has thought about it”.

    Labs

    Break it yourself

    The four hands-on labs from the course, each one a failure you cause on purpose. Links live in the source video’s description.

    Lab 01 · load balancing

    Kill a container mid-request

    Run one app in two containers behind nginx, push a pile of requests through, then shut one container down while it is still busy and watch the balancer route around the corpse.

    Lab 02 · indexing

    Five million rows, one index

    Fill a table with 5M rows, run a query, watch it crawl. Work out why, add a single index, run it again — milliseconds.

    Lab 03 · caching

    Serve stale data on purpose

    Put Redis in front of the database, measure before and after, then change the row underneath and watch your app confidently hand out the old value.

    Lab 04 · replication

    Lag, failover, and a bad DELETE

    Set up a primary and a replica, write a row and read it from the copy a beat too early. Then kill the primary, promote the replica — and watch the replica dutifully copy your delete.

    Glossary

    Say the word, then say why