7 Building Blocks Framework

How Instagram Actually Works: A Building Blocks Breakdown

A billion people post photos that load in under a second. Here is how the building blocks make that possible — and why the parts, not the product names, are what transfer.

A billion people upload photos to Instagram. Every one of those photos shows up, in order, in a feed that loads in under a second. Stories appear, then vanish after 24 hours. A like you tap on a beach in one country lights up a notification on a phone in another.

Most explanations of "Instagram system design" hand you a wall of vendor names. Use Cassandra here. Redis there. A CDN in front. You memorize the diagram for an interview, and you forget it by the weekend, because a list of products is not understanding.

Here is the thing those explanations miss. Instagram is not a special, secret machine. It is built from the same small set of parts that every large system is built from — the same 7 building blocks behind Netflix, Stripe, and the system you are about to be handed at work. Once you can see those parts, you stop memorizing Instagram's architecture and start being able to read any system, including the ones you have not seen yet.

We will walk Instagram's four core flows — posting a photo, loading the feed, Stories, and likes and notifications — and trace each one through the blocks it touches. By the end you will not have memorized Instagram. You will have a way of seeing.

The 7 building blocks, plainly

Before we trace anything, here are the parts. Do not assume you know them. Most "system design" writing throws these words around as if everyone agrees on them. They do not. So here is the plain version.

Every part of a system is doing one of two jobs: handling work or holding data.

Work splits into exactly two modes. That is the complete set. There is no third mode.

Holding data splits into five kinds, by the shape of the data and the question you ask it.

That is seven parts. Two for work, five for data. Plus three outside forces that act on the system: the User (a person taking an action), an External Service (a third party you call, like a push-notification provider), and Time (the clock itself, triggering things on a schedule or after a delay).

Now watch how Instagram falls out of these parts.

Flow 1: Posting a photo

You pick a photo, write a caption, tap Share. The app says "posted" almost instantly. But a lot just happened. Let us trace the request.

The tap hits a Service. Your phone sends the photo and caption to Instagram's API, which is a Service. Something is waiting (you, staring at the screen), so this is synchronous work by definition. The Service's job is to receive the upload, decide what to do with each piece, and return an answer fast.

File Store Block

The photo goes to a File Store. The image itself, two to ten megabytes of binary data, does not belong in a database. Databases are built for structured records you query, not for multi-megabyte blobs. Push photos into the database and you bloat it, slow every query, and make backups painful. So the Service hands the raw image to a File Store, the block built for exactly this: cheap, durable storage of large files, served back later by their address. This is the same decision behind any large photo gallery or video platform you have used.

The caption and metadata go to a Relational Database. Who posted it, when, the caption text, which user it belongs to. That is structured, related data: this post belongs to this user, this user has these followers. A Relational Database is built to hold records and the relationships between them, so that later you can ask "every post by everyone this person follows" and get a real answer.

Queue Block Worker Block

The heavy lifting is handed to a Queue and a Worker. Here is the move that separates a system that feels fast from one that makes you wait. After upload, Instagram needs to generate thumbnails for a dozen screen sizes, compress the image, maybe scan it. That work takes several seconds. Should you sit and watch a spinner while it runs? No.

So the Service does not do that work. It drops a "process this image" task onto a Queue and immediately returns "posted" to you. A Worker, running in the background with no one waiting on it, pulls the task off the Queue and does the slow processing. You are already back to scrolling. The Queue plus Worker pairing is the single most important pattern for making large systems feel instant: accept the request now, do the heavy work after the user is gone.

That is one tap, five blocks. Service to receive it. File Store for the photo. Relational Database for the metadata. Queue plus Worker for the processing. The reasoning, not the product names, is what transfers.

Flow 2: Loading the feed

You open the app and your feed is just there, in order, in well under a second. This is the flow most people get wrong when they first design it, and seeing why is the whole point.

The obvious design is too slow. The naive approach: when you open the app, a Service queries the Relational Database in real time. "Find everyone this user follows, find all their recent posts, sort by time, return them." For one user with a few follows, fine. For a user who follows two thousand accounts, on a platform with hundreds of millions of people refreshing constantly, that query runs across an enormous number of records every single time anyone opens the app. The database melts. The feed takes seconds. People leave.

The Relational Database is the right place to store the relationships. It is the wrong place to answer the feed question on demand, at scale. That tension is the lesson.

The fix is to pre-compute and cache. Instead of building your feed the instant you ask for it, the system builds it ahead of time and stores the finished result keyed by your user ID. When you open the app, the Service does not run a giant query. It does one lookup: your user ID, here is your ready-made feed. That is a Key-Value Store: hand it one key, get one value back, in under a millisecond.

So who builds the feed if not the live request? Workers. When someone you follow posts, a Worker (fed by a Queue, the same pattern as before) fans that new post out into the pre-computed feeds of their followers. The slow work happens in the background, ahead of time. By the time you pull to refresh, the answer is already sitting in the Key-Value Store waiting for you. (At extreme scale, systems blend in a second approach for accounts with millions of followers, to avoid fanning a single post out tens of millions of times, but the pre-compute-and-cache idea is the one to take with you.)

Trace the feed and you see four blocks working together. The Relational Database holds the source of truth. Workers and a Queue do the assembling in the background. The Key-Value Store holds the finished feed for instant delivery. The Service just looks it up and hands it to you.

This is the read-heavy pattern, and once you can see it here you will see it everywhere, because most consumer systems read far more than they write. The design decision underneath it — store the truth in one place but serve a fast pre-built copy from another — is one of the most reusable judgments in all of system design.

Flow 3: Stories

Stories look like a different feature. Under the blocks, they are the photo flow with one new force added: Time.

A story is still an image or video. It still goes to the File Store. Its metadata, who posted it and when, still goes to the Relational Database. It is still delivered fast through the same machinery. Nothing new there.

The new thing is that a story expires after 24 hours. That expiry is not something a user taps. It is the clock acting on the system on its own, which is the external entity Time. Time is a first-class force in system design precisely because so many features depend on something happening because the clock said so, not because a person did anything.

So the design adds a time dimension. Each story carries an expiry timestamp in the Relational Database. A Worker, triggered on a schedule by Time (rather than by a user action), wakes up, finds the stories whose 24 hours are up, and removes them from the active set so they stop being served. Same blocks as a photo, plus Time as the trigger and a Worker doing the scheduled cleanup.

The lesson worth keeping: when a feature's behavior is driven by the clock and not by a person, you are looking at the Time entity, and the work it triggers almost always lands on a Worker, never on a Service. Nobody is waiting, so nothing should block.

Flow 4: Likes and notifications

You tap a heart. Two things have to happen, and they have very different urgency. Telling them apart is the skill.

The like itself must feel instant. You tap, the heart fills red immediately. That part is fast synchronous work: a Service records the like against the post and returns right away. The count updates. You move on. From your side, it is done.

The notification can take its time. Now the person whose photo you liked should get a notification. Does that have to happen in the same instant your heart turns red? No. A second or two later is completely fine, and they may not even have the app open. This is background work, and forcing the User to wait on it would be a mistake.

So the Service does not send the notification itself. It drops a "notify this user" task onto a Queue and returns. A Worker picks it up and does the actual delivery. And delivering a push notification is not something Instagram does alone: it hands the message to Apple's or Google's push system, which is an External Service, a third party the system calls out to. The Worker calls that External Service, the notification arrives on the other person's phone, and the User on the receiving end sees "someone liked your photo."

One heart tap touches a Service (instant like), a Queue and Worker (deferred notification), an External Service (the push provider), and two Users (you and the person you notified). The judgment that matters is the split: the part the user waits on goes to a Service, the part they do not goes to a Queue and a Worker. Tell those two apart and most of system design starts to feel obvious.

The point is not Instagram

Step back and look at what we actually did. We never memorized Instagram's architecture. We took four flows and asked the same questions each time. Who is waiting on this? What shape is this data? What can happen in the background? And the same handful of parts answered every time.

The exact same questions, asked of Netflix, of Stripe, of Slack, of the feature your team is about to hand you, produce the architecture of those systems too. The blocks do not change. Only the arrangement does.

The AI Era Lesson

That shift, from memorizing systems to seeing the parts they are made of, is the entire skill. It is the difference between an engineer who can recite a famous architecture and one who can walk into an unfamiliar system and reason about it out loud.

If you ask AI to "build Instagram," it will give you code that stores a photo and serves it back. That works for one user. It melts the moment the feed query fans out across millions of follows, because AI defaults to the simplest path from input to output. But if you understand the pattern, you can direct it with precision: "Build the feed as pre-computed per-user lists in a key-value store, populated by a fan-out worker off a queue." Now AI has a bounded task, and you made the architectural decision. That is the real skill in the AI era. AI can write the code either way. The judgment about which parts a system should be made of, and why, is yours to build, and it is the part that lasts.

What to Explore Next

The patterns here build directly on the core articles: the Service and Worker split, the three storage extremes that decide File Store vs. Relational vs. Key-Value, the Queue that makes the pre-compute work, and the external entities (User, External Service, Time) pushing on the system from outside.

For other real systems traced end to end, see how Netflix actually works and how Uber works, a real-time system that leans on the Queue and fast storage harder than a content app does. To go deep on the newest block, the one powering Instagram-style "more like this" recommendations and AI search, read what a vector database is. And when you want to choose the right blocks for your own design, the decision framework pulls all of it into a practical guide.

Frequently Asked Questions

How does Instagram store billions of photos?
The photos themselves do not live in a database. They live in a File Store, the block built for large binary files like images and video: cheap, durable storage you fetch back by the file's address rather than by querying it. To serve those files fast to people all over the world, Instagram puts a content delivery network in front of the File Store, which keeps copies of popular photos physically close to the people viewing them. The photo's metadata (who posted it, when, the caption) lives separately in a Relational Database, because that part is structured, related data you actually need to ask questions about.
How does Instagram load your feed so fast?
It does not build your feed the moment you open the app. Building it live, by asking a Relational Database for every recent post from everyone you follow, would be far too slow at Instagram's scale. Instead, Workers running in the background assemble your feed ahead of time and store the finished result in a Key-Value Store, which returns one value for one key in under a millisecond. When you pull to refresh, a Service does a single fast lookup on your user ID and hands you the feed that was already waiting.
What database does Instagram use?
There is no single database, and that is the actual lesson. Instagram uses a mix, and each kind of storage is chosen by the job it does: a Relational Database for users, posts, and who-follows-whom, because that data is structured and related; a Key-Value Store for the pre-built feed, because that job needs raw lookup speed; and a File Store for the photos and videos, because those are large binary files. The point is never the vendor name. It is matching the shape of the data and the question you ask it to the block built for that job.
How do Instagram Stories disappear after 24 hours?
The expiry is driven by the clock, not by anyone tapping a button, which makes it the external force called Time. Each story is stored with an expiry timestamp in the Relational Database, the same way a normal post's metadata is stored. A Worker, triggered on a schedule by Time rather than by a user, wakes up, finds the stories whose 24 hours are up, and removes them from the active set so they stop being served. Nobody is waiting on that cleanup, so it belongs on a background Worker, never on a Service.

Don't just read it — build with it

You can't read your way to judgment. Put this block into practice: map your own app with Design with Blocks, or play the building blocks game with Instagram, Netflix, and Uber.

Design with Blocks Play the Game