Skip to main content

Design Instagram

Premium

You're asked to design a social photo-sharing app like Instagram, usually scoped to posting and the home feed. Users upload photos, and their followers see those photos in a personalized feed that loads in under a second. The system may hold billions of posts, but each feed needs only the recent ones that matter to that user.

The hard part is deciding when to build the feed. Assembling it from scratch on every read does not scale to hundreds of millions of daily users. Building every feed ahead of time works well until an account with 400 million followers publishes a post. Let's compare those approaches and arrive at a practical compromise.

Clarify the requirements

  • Which surfaces are in scope? Instagram includes posting, the home feed, search and explore, stories, direct messages, and reels. You cannot cover all of them in one interview. Start with posting and the home feed, then let the interviewer redirect if needed.
  • Is the feed chronological or ranked? A reverse-chronological feed requires a merge. Ranking adds a scoring layer and changes what the system can precompute.
  • How fresh should the feed be? Ask whether new posts must appear within seconds or whether a minute is acceptable. That freshness budget guides the rest of the design.
  • How are followers distributed across accounts? Most accounts have an ordinary number of followers, while a few have hundreds of millions. That distribution will force a hybrid design.

For this design, assume that posting, media, and a reverse-chronological home feed are in scope. New posts should appear within seconds.

Back-of-envelope numbers

  • Feed reads: 500M DAU×10 opens/day≈60k reads/sec500\text{M DAU} \times 10 \text{ opens/day} \approx 60\text{k reads/sec}
  • Posts: 100M posts/day≈1,200 posts/sec100\text{M posts/day} \approx 1{,}200 \text{ posts/sec}, roughly a 50:1 read-to-write ratio
  • Timeline writes if fanning out on write: 1,200 posts/sec×200 followers≈240k writes/sec1{,}200 \text{ posts/sec} \times 200 \text{ followers} \approx 240\text{k writes/sec}
  • Media: 100M posts/day×2 MB≈200 TB/day100\text{M posts/day} \times 2\text{ MB} \approx 200\text{ TB/day}

The 50:1 read-to-write ratio points toward optimizing reads. But 240k timeline writes per second is still substantial, so precomputing feeds will not be free.

High-level architecture

upload

post metadata

GET /feed

Client

① Object storage

② Post service

③ Post store

④ Fan-out queue

⑤ Fan-out workers

⑥ Timeline cache

⑦ Feed service

⑧ CDN

Components
  1. Object storage. Photos and videos upload directly through presigned URLs, so the bytes never pass through the application servers.
  2. Post service. Writes post metadata and publishes a PostCreated event.
  3. Post store. Holds the durable record of every post, partitioned by user.
  4. Fan-out queue. Decouples posting from the expensive follower fan-out.
  5. Fan-out workers. Look up followers and push the post ID into each of their timelines.
  6. Timeline cache. Keeps an in-memory list of recent post IDs for each user.
  7. Feed service. Reads the timeline list and hydrates each post with its content and counts.
  8. CDN. Serves the media, which accounts for most of the system's bandwidth.
The write path fans a new post into follower timelines asynchronously; the read path serves a precomputed timeline from cache. Media never passes through the app tier.

Deep dive 1: fan-out on write versus fan-out on read

The central choice is whether to build timelines when posts are written or when feeds are read. Both approaches have a clear cost.

Fan-out on write (push). When a user posts, write the post ID into every follower's timeline. Reading the feed is then a matter of fetching a list and hydrating its posts. The write costs O(followers).

Fan-out on read (pull). Store no extra timeline data. When a user opens the app, look up the accounts they follow, fetch recent posts from each one, and merge the results. Writes are cheap, but every feed read requires O(following) queries and a merge.

With a 50:1 read-to-write ratio, push is the better default. The system does the expensive work 1,200 times per second instead of 60,000, and most feed reads become cache lookups.

Deep dive 2: the celebrity problem

Push runs into trouble with accounts that have enormous followings. A post from an account with 400 million followers creates 400 million timeline writes. That can saturate the fan-out fleet, leave other posts waiting in the queue, and add minutes of lag across the system.

A hybrid handles both cases. Use fan-out on write for ordinary accounts, but skip it when an account exceeds a follower threshold. At read time, the feed service merges the user's precomputed timeline with recent posts pulled from the celebrity accounts they follow. Those posts receive so much traffic that they are likely to be in cache, which keeps the pull cheap.

Treat the threshold as a tuning parameter rather than a fixed constant. Roughly one million followers is a reasonable starting point, then adjust it based on observed fan-out lag. The read-time merge also stays manageable because even users who follow many celebrities usually follow only a few dozen of them.

Deep dive 3: what the timeline actually stores

Store post IDs, not post content. Each timeline entry needs only an ID and a timestamp, which keeps the list small enough to hold in memory. The feed service can hydrate a batch of IDs from the post cache in one lookup.

Post content can change, but IDs do not. If every follower's timeline contains a copy of the post, editing a caption or deleting the post requires finding and rewriting millions of entries. With ID-only timelines, deletion takes one write, followed by a filter when the feed hydrates its posts.

Cap the length of each timeline so memory use remains predictable as the user base grows. Few people scroll past a few hundred posts, so keep roughly that many entries in memory and fetch anything older from the post store. The total memory requirement is straightforward to estimate: 500M users×500 entries×16 B≈4 TB500\text{M users} \times 500 \text{ entries} \times 16\text{ B} \approx 4\text{ TB}. That is large, but tractable across a fleet.

Deep dive 4: storing and serving media

Images and video add roughly 200 TB per day at the scale estimated above. They do not belong in the application database or on the path through the application servers. A single upload could occupy a request thread for seconds and consume bandwidth needed by the rest of the service.

The client should upload directly to object storage with a presigned URL from the API. The application servers then handle only the small metadata write. After the upload finishes, an event starts a processing pipeline that generates thumbnails and several display resolutions. A CDN serves the finished media from an edge location instead of sending every byte from the origin. This is the media streaming pattern at a smaller scale.

Deep dive 5: scaling to 10x traffic

At ten times the traffic, watch these three parts of the system first:

  • The fan-out fleet may fall behind during peak posting hours. Track the age of the oldest queued fan-out job rather than raw queue depth. Queue depth alone does not reveal how stale the feeds have become.
  • Timeline cache memory may become the binding constraint. The cap on timeline length keeps this growth under control.
  • Hot posts can concentrate hydration traffic on individual cache keys. When millions of users request the same post, replicate its key across cache nodes.

Common pitfalls

  • Choosing fan-out on write without addressing celebrity accounts. This is a common follow-up to the initial design.
  • Storing post content in timelines. Edits and deletions become a distributed find-and-replace.
  • Routing media through the app tier. Use presigned uploads and CDN delivery.
  • Unbounded timelines. Memory grows without limit for users who follow thousands of accounts.
  • Synchronous fan-out. Posting should not wait on 200 timeline writes.

Leveling signals

Mid-levelIdentifies the workload as read-heavy, separates media from metadata, and describes a feed built from precomputed timelines with a cache in front.
SeniorChooses fan-out on write deliberately, raises the celebrity problem unprompted and designs the hybrid, stores IDs rather than content, and moves fan-out off the posting path.
Staff+Sets a freshness budget per surface and sizes the timeline cache against it. Treats like counts as their own high-write problem, and names what degrades first at 10× along with how it's detected.
Design TwitterHard

Build a timeline of posts from followed accounts, plus trending topics.

Design the Reddit HomepageMediumPlanned

Rank and serve a homepage of posts that reorders as votes come in.