DEV Community

RONI DAS
RONI DAS

Posted on • Originally published at systemdesign.academy

Designing Instagram: the feed, the storage, and the parts that break at scale

Instagram is a good interview question precisely because it looks trivial. Upload a photo, show a feed, done. But two of those words, "photo" and "feed," each hide a real system, and the interesting decisions are about how you store the first and assemble the second.

Start with the photo. The mistake beginners make is storing image bytes in the main database. Databases are for structured data you query and update: users, captions, likes, follows. They are the wrong home for large binary blobs. So the first decision is to split storage in two. Image and video files go into an object store, the kind of blob storage that is cheap, durable, and sits behind a CDN. The database only holds a pointer to that object, plus the metadata around it. When someone uploads a photo, you generate a few resized versions right away, thumbnail through full size, store them in the object store, and record their locations. The feed then serves image URLs that resolve to a CDN edge near the viewer. The trade-off is that you now manage two systems that can drift out of sync, but you gain cheap durable storage and fast global delivery, which is exactly what images need.

Now the feed, which is the real question. When you open the app, you want a list of recent posts from the accounts you follow, newest first, fast. There are two honest ways to build this and the choice is a classic trade-off.

The first is fan out on read. When you open your feed, the system looks up everyone you follow, fetches their recent posts, merges them by time, and returns the result. This is simple and writes are cheap, because posting a photo just inserts one row. The cost lands at read time, and it lands hardest on people who follow thousands of accounts, because assembling their feed means gathering from thousands of sources on every refresh.

The second is fan out on write. When you post, the system immediately pushes a reference to that post into a precomputed feed list for each of your followers. Reading is then trivial, because each user's feed is already sitting there ready to return. The cost moves to write time, and it gets ugly when someone with millions of followers posts, because that one action has to update millions of feeds.

Neither wins outright, so real systems use a hybrid. Most users get fan out on write, so their feed is precomputed and reads stay cheap. But accounts with huge follower counts are treated as an exception. Their posts are not fanned out to everyone. Instead they are pulled in at read time and merged into the precomputed feed. You pay the write cost for the many normal accounts and the read cost only for the few enormous ones. That single split, ordinary users precomputed and celebrities pulled live, is the heart of the design.

There is a caching layer wrapped around all of it. The feed lists live in an in memory store so a refresh does not hit the database. Counts like likes and follower totals are cached and updated asynchronously, because showing a like count that is a second or two stale is fine, and doing an exact live count on every view is not. Accepting slightly stale counts in exchange for speed is a deliberate and reasonable call.

Sharding shows up next. You cannot keep everything on one database, so you split data across many, and the choice of shard key matters. Sharding by user id keeps a single user's data together, which helps profile reads. It complicates queries that cross users, which is why the feed is precomputed rather than assembled with a giant join at read time. A lot of the design exists to avoid queries that would have to touch many shards at once.

How does the real company do it? Instagram famously ran on a relatively small, disciplined stack for a long time: a straightforward relational database sharded across many machines, blob storage plus a CDN for media, and an aggressive in memory cache in front. They leaned on precomputed feeds with special handling for high fan out accounts, and they were willing to accept eventual consistency on counts and ordering to keep the app fast.

The lesson worth taking away is that "store the photo" and "show the feed" are two different problems with two different data stores, and the feed is really a question about when you pay: at write time or at read time.

I wrote the full breakdown, with diagrams and the data model, here: https://www.systemdesign.academy/interview/design-instagram

Top comments (0)