LearnastraTHE DESIGN COURSE

Design complete systems / CHAPTER 50

Design a photo-sharing service (Instagram)

Let authors publish complete photos and followers browse them, then separate image delivery from the work of building feeds.

Advanced3h 20m of deliberate study10 questions

Builds on Design a text-sharing service (Pastebin), Synchronous versus asynchronous communication, Caching fundamentals, Read-heavy versus write-heavy workloads.

By the end, you can
  • Publish a post only after all required images are ready.
  • Calculate image bytes separately from the database work for a feed.
  • Combine prepared home lists with read-time author queries, while checking current access.
INTERVIEW STEP 1 / 7Clarify the requirements

01Functional requirements

The product stores photos and shows posts from followed authors. The original is the uploaded image; display variants are smaller prepared copies for different screens.

  1. FR1: Upload and manage photos. Let an author upload an original photo, check processing progress, publish it and remove it. Prepare the required display sizes before publishing; viewers must not receive a half-prepared photo.

  2. FR2: View and download. Check the viewer’s permission, then return photo details and a prepared image large enough for the requested display dimensions. Avoid sending the full original for a small feed preview. Support public photos and photos restricted to an approved audience.

  3. FR3: Search titles. Find published photos by title. Check current visibility before returning a title, snippet or image reference.

  4. FR4: Follow accounts. Support following, unfollowing and approval for private accounts. Removing approval must remove access even if an old feed entry still mentions the photo.

  5. FR5: Generate home feeds. Show posts from followed authors, with pages that do not shuffle unpredictably while the viewer moves through them. Begin with newest-first ordering and use it if optional ranking fails.

Out of scope

  • Video, photo tags or tag search, user tagging and comments.
  • Suggestions about whom to follow and posts from outside the follow graph.

Example: Mira uploads p81, “Garden opening.” Ben follows her, searches its title and sees it in his home feed.

02Nonfunctional requirements

Assume ten million daily active users. Five percent upload two photos each day; each user views 100 photos. These are planning assumptions to confirm and test.

  1. NFR1: Feed latency. At least 95% of primary-region feed requests finish within 300 ms at the planned peak. Downloading images is measured separately.

  2. NFR2: Feed availability. Feed requests meet 99.9% availability per calendar month. If optional ranking fails, return posts ordered by creation time, newest first.

  3. NFR3: Media durability. Published originals and required display sizes survive one storage-node failure under the selected storage service's guarantees. Unfinished temporary uploads are excluded; this is not a promise that data can never be lost.

  4. NFR4: Publication readiness. Verify every required image before publishing its reference. At normal load, at least 95% of valid uploads publish within 30 seconds. Show failures and allow retries.

  5. NFR5: Audience revocation. Check current approval before issuing private-image download credentials. Previously issued credentials expire within 60 seconds. Already downloaded images cannot be recalled.

  6. NFR6: Search, feed and pagination behavior. A photo may become searchable or appear in feeds shortly after publication rather than instantly. For ranked pages, save the ordered post IDs and continue from the last returned position; use post ID to order equal scores. Unrelated photos do not need one globally agreed creation order.

  7. NFR7: Isolate expensive work. Limit simultaneous image validation, resizing, feed updates and retries separately. A slow transform or an author with millions of followers must not consume every resource needed to serve feeds.

INTERVIEW STEP 2 / 7Estimate the scale

03Calculate the media budget

  1. Uploads: 5% of ten million users = 500,000 uploaders. Two photos each gives one million/day, about 12 uploads/second on average.
  2. Stored images: one million × 4 MB originals = 4 TB/day. Display variants adding 30% bring the total to 5.2 TB before replicas and backups.
  3. Displayed bytes: ten million viewers × 100 photos = one billion image displays/day, about 11,600/second. At 50 KB per display, transfer 50 TB/day. Serving smaller prepared sizes and nearby cached copies matters far more than enlarging caption rows.
  4. Follower updates: a post by an author with ten million followers may need ten million home-list insertions. Measure active followers and posting rates; average upload rate cannot size that burst.

Decisions: store originals durably, prepare copies for the display dimensions the application supports and deliver repeated images through a content delivery network. Put follower-list work in limited background workers, and compare prepared lists with merging large-author posts when viewers read.

INTERVIEW STEP 3 / 7Define the API

04API Design: Requests, Responses and Retries

Reserve bytes separately from publication:

POST /uploads
Idempotency-Key: upload-81
{"mediaType":"image/jpeg","byteLength":4000000}
{"uploadId":"u81","putUrl":"<scoped-url>","expiresInSeconds":900}

Publish the uploaded photo

  1. Send the image to the upload URL within 900 seconds. The URL permits only this reserved upload.
  2. Call POST /posts with request key publish-81 and {"uploadId":"u81","title":"Garden opening","caption":"Come Saturday","visibility":"followers"}.
  3. The service returns 202 Accepted and {"postId":"p81","state":"processing"} while it prepares the required display sizes.
  4. Check GET /posts/p81. When all required images are ready, it reports published state and their versioned locations.

Retries and errors

  • The same key and content return the same post ID; the retry does not publish a second post.
  • Changed content under that key returns 409 Conflict.
  • An oversized upload returns 413; an unsupported media type returns 415.
  • Reading a private post without permission returns 403. Reading a deleted post returns 410.

Browse and change access

  • GET /authors/M/posts?cursor=... lists Mira's posts; M is her account ID.
  • GET /home?cursor=... lists a home-feed page, for example {"items":[{"postId":"p81","mediaVersion":1}],"cursor":"<ranking-view-cursor>"}.
  • GET /photos/search?q=garden&cursor=... searches titles. Each cursor identifies where the next page continues.
  • Ben calls PUT /authors/M/follow to follow Mira and DELETE /authors/M/follow to unfollow. A private account records the follow as pending until Mira approves it.
  • Mira calls PUT /followers/Ben/approval to approve Ben or DELETE /followers/Ben/approval to revoke approval. The handler checks that the signed-in account owns the private account before changing that relationship. Repeating either operation leaves the same final relationship state.
  • Mira calls DELETE /posts/p81. The handler checks ownership and saves the deleted state before returning success; repeating deletion succeeds without creating another operation. Supplying another ownerId cannot grant permission.
INTERVIEW STEP 4 / 7Define the data model

05Data Model and Storage Access Patterns

A published post is the original record. Search hits and feed entries are copies used to find posts; they do not independently decide whether a viewer may see one.

Record and index What it stores or answers
Post, postId Author, title, caption, visibility, publication state, creation time and version
Upload, uploadId; create request, (authorId,requestKey) Reserved object, length/type and expiry; original creation fields and the resulting post ID for retry comparison
Image task, (postId,mediaVersion,taskName) Required output, current attempt ID and completion state
Pending publication work, (postId,version) Feed/search update still needing delivery after publication
Author index, (authorId,createdAt,postId) Find one author's recent posts in order
Image variant, (postId,mediaVersion,size) Object location, dimensions and checksum for one prepared image size
Follow, (followerId,authorId); reverse author index Check current approval and find an author's followers
Home entry, (viewerId,postId) A candidate post for one viewer, with ranking hints and a unique insertion key
Search document, postId Searchable title terms and the version copied from the original post

The author index begins with authorId because the query asks for one author's posts. A globally unique postId alone cannot efficiently answer that query.

INTERVIEW STEP 5 / 7Draw the high-level design

06Complete upload before optimizing feeds

Start with an application, a database for post details and private object storage for image bytes. A variant is a prepared size of the photo, such as a thumbnail or display image.

Upload and publish

  1. Mira requests upload u81 and sends the original image. u81 identifies this upload; publish-81 identifies her later request to create a post from it.
  2. The application checks actual length, type and checksum. An image-processing worker decodes it outside the feed-serving process, with memory and time limits for malformed files. For this example, remove embedded GPS coordinates from display copies, then create the required image sizes.
  3. Save each processing task under its post, version and task name. After a crash, another worker checks completed outputs and retries only missing work. Do not rely on an in-memory callback.
  4. After verifying every required output, the worker asks the database to publish p81 only if its saved post version, processing state and task attempt still match. In that same transaction, save the feed/search work to deliver. A delayed worker cannot republish a post that Mira deleted or a newer task replaced. Readers cannot see a partially prepared photo.
  5. Clean abandoned uploads only after their deadline and grace period, while protecting active tasks.

Serve the first feed and search

  1. Ben follows Mira. The feed handler reads recent posts from followed authors, removes posts Ben may not see and merges the rest newest first.
  2. The response names a prepared image that meets the requested display dimensions, rather than always sending the large original.
  3. Title search can initially use a database text index. Before showing a title, snippet or image, check that the original post is still published and permitted.

At small load, the application may receive upload bytes itself. Later let clients upload directly through restricted storage URLs and run image processors separately. Reserving, verifying and publishing remain distinct steps.

BUILD THE DESIGN, ONE CHANGE AT A TIME

Watch the architecture evolve.

Advance through the stages in this same diagram. Existing components keep their places; additions fill the available space, then add rows. Highlights show what changed from the previous stage, and numbered arrows match the connection key below.

Stage 1 of 3

RetainedAdded / new routeChanged responsibility / route

Start here. Verify that upload, required variants, publication and an authorized feed work before adding distributed views.

Stage 1: read-time feed with verified media

Stage 1: read-time feed with verified mediaThe image worker verifies upload u81 and prepares the required sizes. The database publishes p81 only if the current processing version is complete. For Ben’s feed, the API merges a limited number of followed-author posts and checks current approval. Numbered arrows correspond to the connection key below. All connections are directional.Photo clientReserve, upload orbrowsePhoto API +workerCheck access; prepareimages and feedMetadata databasePosts, followers andsaved workPrivate mediastoreVerified originals +required variants1234Stage 1: read-time feed with verified mediaThe image worker verifies upload u81 and prepares the required sizes. The database publishes p81 only if the current processing version is complete. For Ben’s feed, the API merges a limited number of followed-author posts and checks current approval. Numbered arrows correspond to the connection key below. All connections are directional.Photo clientReserve, upload orbrowsePhoto API +workerCheck access; prepareimages and feedMetadata databasePosts, followers andsaved workPrivate mediastoreVerified originals +required variants1234Stage 1: read-time feed with verified mediaThe image worker verifies upload u81 and prepares the required sizes. The database publishes p81 only if the current processing version is complete. For Ben’s feed, the API merges a limited number of followed-author posts and checks current approval. Numbered arrows correspond to the connection key below. All connections are directional.Photo clientReserve, upload orbrowsePhoto API +workerCheck access; prepareimages and feedMetadata databasePosts, followers andsaved workPrivate mediastoreVerified originals +required variants1234

Follow the numbered arrows

  1. Photo client → Photo API + workerUpload / feed request
  2. Photo API + worker → Metadata databaseSave posts; query authors; check access
  3. Photo API + worker → Private media storeProxy bytes / prepare variants
  4. Photo API + worker → Photo clientAuthorized metadata / display bytes
The metadata database stores current visibility. Saved job records let image processing resume after the application restarts.
Trace the diagram in words
  1. The image worker verifies upload u81 and prepares the required sizes.
  2. The database publishes p81 only if the current processing version is complete.
  3. For Ben’s feed, the API merges a limited number of followed-author posts and checks current approval.
What this stage establishes
  • Keep the original post and follow records together in one metadata database.
  • Run durable media jobs alongside the API and merge followed authors on reads.

The cost: The baseline is easy to repair but heavy image work competes with feed requests and every feed repeats author queries.

Read the reasoning for this stage →
Smallest working system
INTERVIEW STEP 6 / 7Go deep

07Evolve media delivery and feed generation

Deliver image bytes efficiently

  1. Prepare the sizes needed for thumbnails, small screens and large screens. Serve these through a content delivery network, which keeps reusable copies near viewers.
  2. Unchanged public images can have long cache lifetimes, with a stated deletion/purge policy.
  3. Private downloads require a fresh permission gate or temporary credentials within the revocation limit. A stale feed entry is not permission to download.

Prepare feeds for ordinary authors

  1. After publication, a relay reads the saved feed-update record and passes it to a background program that finds Mira’s active followers. If the relay crashes before saving its delivery confirmation, it may send the same update again.
  2. It inserts p81 into each follower's recent home list. Use a unique (viewerId,postId) pair so retrying an insertion cannot add the post twice.
  3. Ben's next request reads that prepared list, loads current post details and checks permission before returning images.
  4. This is fan-out-on-write: one publication triggers many background feed writes, reducing later read work. Keep only a limited recent window, grouped by viewer.

Handle very large audiences differently

  1. One author with ten million followers can require ten million feed insertions for one photo.
  2. Keep that author's recent posts in an author index instead. When Ben requests his feed, merge a limited number of those posts into his prepared list.
  3. The hybrid combines prepared lists for ordinary authors with read-time merging for large audiences. Estimate feed insertions/second as the author’s posting rate × active followers. Use read-time merging when those insertions would exceed the workers’ tested capacity or make posts appear later than the feed’s freshness target; include the added author reads in the comparison.
See stage 2: Separate media path ↗

08Choose IDs and metadata partitions

Choose capacity before partitioning

  • Add database memory if that solves the current limit. Replicas can serve public metadata when a short delay is acceptable.
  • Mira's immediate “published” confirmation must read a copy known to include her saved publication.
  • Scale request handlers separately from image workers so resizing does not consume all feed-serving resources.
Place records by Benefit Cost
authorId One author's recent posts stay together A popular author can overload its partition
Random postId Spreads individual post rows Need an author/time index to find one author's posts
Creation-time range Efficient archive ranges New traffic concentrates on the latest partition

Retrieve records after finding IDs

  1. Mira's posts p81 and p82 may live on partitions 2 and 7. An author/time index lists their IDs in order.
  2. The feed handler groups those IDs by partition and fetches their current titles, visibility and image references in batches. This is sometimes called hydration: loading the details behind an ID.
  3. Map logical partitions to machines so selected groups can move during growth. A modulo directly tied to machine count can move many records on every resize.

Choose IDs separately from storage placement

  • A database sequence issues distinct integers; assigned ranges can reduce calls to the issuer.
  • Random IDs need duplicate handling and do not imply creation order.
  • Time/worker/sequence IDs and UUIDv7 carry time information. For a time/worker/sequence generator, assign each worker a distinct worker ID, wait when its sequence for one clock tick is full, and stop or wait if its clock moves backward. These rules prevent reusing an earlier combination. Such IDs still do not establish one agreed publication order across all authors; use the index required by the listing query.

Find Mira’s recent photos even when their records are spread out

Find Mira’s recent photos even when their records are spread outRead the author-time index to identify recent photos. Group the resulting IDs by their metadata partition. Load current post details and check who may see it before ranking or issuing downloads. Numbered arrows correspond to the connection key below. All connections are directional.Mira author indexp82 then p81 by timePost p81Hash partition 2Post p82Hash partition 7Load current postdetailsFetch several recordsper partition1234Find Mira’s recent photos even when their records are spread outRead the author-time index to identify recent photos. Group the resulting IDs by their metadata partition. Load current post details and check who may see it before ranking or issuing downloads. Numbered arrows correspond to the connection key below. All connections are directional.Mira author indexp82 then p81 by timePost p81Hash partition 2Post p82Hash partition 7Load current postdetailsFetch several recordsper partition1234Find Mira’s recent photos even when their records are spread outRead the author-time index to identify recent photos. Group the resulting IDs by their metadata partition. Load current post details and check who may see it before ranking or issuing downloads. Numbered arrows correspond to the connection key below. All connections are directional.Mira author indexp82 then p81 by timePost p81Hash partition 2Post p82Hash partition 7Load current postdetailsFetch several recordsper partition1234

Follow the numbered arrows

  1. Mira author index → Post p81Resolve recent post ID
  2. Mira author index → Post p82Same author, different shard
  3. Post p81 → Load current post detailsCurrent metadata
  4. Post p82 → Load current post detailsCurrent metadata
Randomly placed post rows may put p81 on partition 2 and p82 on 7. The author/time index first lists Mira’s recent IDs, then the application fetches those records in batches.
Trace the diagram in words
  1. Read the author-time index to identify recent photos.
  2. Group the resulting IDs by their metadata partition.
  3. Load current post details and check who may see it before ranking or issuing downloads.

10Follow a photo to a viewer

  1. Upload: Mira sends her original under upload u81. Workers verify it and create all required display sizes.
  2. Publish: check the current processing version and task attempt, then save p81 as published with version 1 and its pending feed/search update in one database transaction. Both records survive an application crash; a late worker cannot restore a deleted post.
  3. Index the title: a background program adds “Garden opening” to title search. Search still checks the current post and audience before showing a result.
  4. Prepare Ben's feed: insert (Ben,p81) only if that pair is absent. A repeated publication event cannot create another entry.
  5. Read the feed: combine Ben's prepared list with recent posts from exceptional large authors, fetch current details and check permission. Return the page with a cursor naming its saved post order and last returned position.
  6. Download: Ben fetches a prepared image large enough for his display dimensions through the delivery network. A small feed preview need not download the 4 MB original.
  7. Delete or revoke: Mira removes p81 or Ben's approval. Stop issuing new private-media credentials immediately according to the stated permission check. Previously issued private-image credentials expire within 60 seconds. A cached image must still require a valid credential; deleting a feed/search entry alone does not block its download. An image already downloaded to Ben’s device cannot be recalled.

Keep delays explicit

  • Publication can finish before title search catches up.
  • An old feed can still contain a deleted post's ID, so the read must check current state.
  • Previously issued download credentials may work until expiry; already downloaded bytes cannot be recalled.
INTERVIEW STEP 7 / 7Find bottlenecks and failure points

11Explain operation, abuse and trade-offs

  1. A required image fails: leave the post processing or failed, save which output is missing and retry within a limit. Do not publish broken required images.
  2. The prepared feed fails: a limited author-query merge can fall back, but cap source queries. Hundreds of new database reads per failed feed request could spread the outage.
  3. Deletion cleanup lags: save current deleted/private state first and block fresh credentials. Remove old feed/search entries in the background while filtering them during reads.
  4. Cleanup races processing: keep any object needed by active image tasks or retained versions. An unfinished upload is not automatically abandoned.
  5. Abuse: verify actual media type, enforce quotas, handle embedded location data deliberately and limit rapid follow changes.
  6. Measure: track request latency, publication time, queued feed-update age, permission denials, cache reuse and bytes delivered. Compare image-processing cost with repeated downloads, and prepared-feed writes with repeated author reads.

OPTIONAL DESIGN EXTENSIONWhere AI Fits in This Design

Use: draft an accessible photo description

  1. Input: one prepared image that passed the upload checks, after Mira agrees to send it to the caption service. Sending it for captioning does not make the photo public.
  2. Output: a suggestion such as “raised garden beds beside a path,” saved separately with post, media and model versions.
  3. Integration: run after media preparation, outside the 300 ms feed request. Optional caption failure must not block required display images from publishing.
  4. Author decision: Mira can accept or edit the description. The model cannot identify people without evidence, alter her title or expand the audience. An old-version result cannot replace a newer approved caption.
  5. Fallback: use creator-written text or honestly indicate that no description is available.
  6. Evaluation and limits: test whether descriptions name visible objects, omit useful details or invent identities, emotions or events that the image cannot establish. Limit image size, retries, queue delay and cost. Obtain permission before sending private images to a model, restrict who can access that processing service, and delete caption copies when the post’s retention rule requires it. A caption must not remain publicly readable after its source photo becomes private.

Microsoft's image-caption documentation illustrates possible outputs. Confidence is a review signal, not proof of correctness.

DRAW. CALCULATE. EXPLAIN.

Survive image-worker failure and a celebrity post

75 minutes · guided practice

Mira starts publishing posts p81 and p82, whose metadata is placed on database partitions 2 and 7. Ben follows her, searches for garden and requests a ranked home page. Only two of p82’s three required image sizes are ready. Ben then loses approval to view her private account, while old feed and search entries remain. Another author, Lee, posts to ten million followers.

  1. Draw how a complete post is published and indexed; explain why p82 must wait.
  2. Show how the feed finds posts across partitions and checks Ben’s current permission.
  3. Choose which authors use prepared follower feeds and which are merged at read time; explain how this handles Lee’s burst.
  4. Calculate cache space for 1 million 1 KB metadata rows and 100,000 50 KB display images.
Your self-check
Compare the worked solution
  1. For each photo, save restartable tasks to prepare the required sizes. p81 can publish when all its outputs are verified and its processing version is still current. p82 remains processing while its third size is missing. Save the publication and feed/search work in the same database transaction.
  2. An author/time index lists Mira’s recent post IDs even when the posts live on different partitions. The feed groups IDs by partition to fetch current records in batches.
  3. Search finds possible IDs. Each result checks the original post’s current state and audience before returning its title or image.
  4. Ben’s prepared feed may retain p81 after approval is removed. Filter it during reads and stop fresh private-media credentials; issued credentials follow their short expiry.
  5. Give ordinary authors unique viewer/post list entries so retries add no duplicates. Merge exceptional large authors at read time, preserving the page’s ordered ranking view.
  6. One million 4 MB originals add 4 TB/day; 30% extra display sizes add 1.2 TB. One billion 50 KB displays transfer 50 TB/day. One million 1 KB metadata rows need 1 GB raw cache; 100,000 50 KB display images need 5 GB.

The checkboxes record your own assessment. The worked solution gives you a way to check the reasoning.

RETRIEVE BEFORE YOU REVEAL

Keep the important ideas.

Say the answer aloud, then turn the card over.

CARD 01What connects a photo to the complete product?
  1. Verify the original and required display sizes.
  2. Publish one post with saved feed/search work.
  3. Copy post IDs into discovery lists.
  4. Load current post details and permission before returning media access.
CARD 02Why does random post sharding need another index?

Random post IDs spread rows but scatter an author’s photos.

  1. An author/time index finds recent IDs.
  2. Batch-fetch their current records by partition.
  3. Check permission before display.
CARD 03Why retain both feed and search checks after publication?
  • A feed or search entry only identifies a possible result.
  • Load the original post and check its current state and audience.
  • Optional AI captions do not decide image readiness or permission.
Practise this topic in the revision deck ↗

CHECK THE REASONING

Can you explain the choice?

Answer every question, then finish for an immediate score and an explanation for each answer. Aim for 80%, then revisit any gaps.

1 / 10Mira’s original image uploaded, but only one of three required display sizes exists. What state should her post have?
2 / 10Mira's photos hash to partitions 2 and 7. Which index supports her recent-photo page?
3 / 10Why can title search return p81 later than its publication?
4 / 10Ben loses approval after his feed contains p81. What should the feed read do?
5 / 10Why might p90 rank before the newer p81?
6 / 10Which partition choice tends to concentrate fresh traffic?
7 / 10Why separate transformation workers from feed-serving capacity?
8 / 10A public metadata replica lags after publication. How can Mira confirm her own post?
9 / 10One billion displayed variants per day average 50 KB each. What is raw daily delivery volume?
10 / 10The optional AI caption for p81 times out after required image variants are ready. What fits the contract?
0 of 10 answered

CLOSE THE LOOP

Explain it without the page.

Summarise the mechanism, one trade-off, and one failure mode. Then mark this chapter complete.

Go to the source