Part VI β The Blueprint Β· Lesson 11.2
HLD β Photo Sharing App (Instagram)
In one lineAn image pipeline feeding an infinite feed β the two hard problems are upload and scroll.
Where you've seen itPosting a 4MB photo that appears almost immediately, then scrolling past a hundred images without a single frame drop.
Diagram
1β2 Β· SCOPE AND SCALE
in scope feed Β· post detail Β· upload Β· like/comment Β· profile
out stories Β· reels Β· DMs Β· search Β· ads
scale 500M DAU Β· ~30 posts/session Β· 4MB in β 200KB out
mobile web first Β· median device mid-tier Android3 Β· ARCHITECTURE
ββββββββββ feed page βββββββββββ ββββββββββββββββ
β Client ββββββββββββββββΊβ BFF βββββββββΊβ feed service β
βββββ¬βββββ cursor API βββββββββββ β post service β
β β user service β
β direct upload (presigned URL) ββββββββββββββββ
βΌ
ββββββββββ trigger ββββββββββββββ write βββββββββββ
β Object ββββββββββββββΊβ transcoder ββββββββββββΊβ CDN β
β store β β (variants) β ββββββ¬βββββ
ββββββββββ ββββββββββββββ β
βΌ
images served from the edge
Upload bypasses the API server entirely β the browser PUTs
straight to object storage with a short-lived presigned URL.6a Β· DEEP DIVE β UPLOAD, and why it feels instant
select file
β
βββΊ client-side downscale on a canvas (4MB β 400KB)
β cuts upload time ~10Γ on mobile data
βββΊ show LOCAL preview immediately (URL.createObjectURL)
β optimistic post appears in the feed at once (6.9)
βββΊ PUT to presigned URL, chunked, resumable
β progress bar from the upload progress event
βββΊ server transcodes to variants: 320 / 640 / 1080 / webp+avif
post flips from "uploading" to live
Failure path: keep the file in IndexedDB (6.5), retry on reconnect.6b Β· DEEP DIVE β FEED SCROLL AT 60fps
cursor pagination (10.11) no duplicates when new posts arrive
virtualization (10.7) constant DOM size, flat memory
<img srcset> + sizes right variant per device pixel ratio
fetchpriority=high on #1 the LCP image (5.5)
loading=lazy below fold never on the first card
aspect-ratio boxes reserve space β CLS β 0 (5.1)
IntersectionObserver prefetch next page 400px earlyHow it works
- Feed = cursor-paginated, normalized store (6.6) so a like updates the post everywhere at once.
- Images dominate everything β variants, modern formats, and correct
sizesmatter more than any JS optimisation. - Upload is direct-to-storage with client-side downscaling and an optimistic local preview.
- Interactions (like, follow) are optimistic with rollback (6.9).
- Rendering: SSR or SSG the shell for LCP, hydrate the feed, stream below-the-fold content (5.6).
Trade-offs
| Choice | Cost |
|---|---|
| Client-side downscale | CPU on device, slight quality loss |
| Direct-to-storage upload | Presigned URL plumbing, harder validation |
| Optimistic posting | Rollback UI when transcoding fails |
| Virtualized feed | Complexity, harder Ctrl-F and SEO |
Interview angle
"The feed janks after a minute of scrolling. Why?"
- Unbounded DOM: every scrolled card is still mounted, so memory and layout cost grow linearly β virtualize.
- Images: wrong variant for the device, no
aspect-ratiobox, decoding on the main thread β usesrcset, reserved space, anddecoding="async". - Then verify with a flame chart (5.4) rather than guessing; long tasks name the culprit.
Recap
- Two hard problems: upload latency and scroll performance.
- Downscale on the client, upload direct to storage, preview optimistically.
- Cursor pagination + virtualization + correct image variants carry the feed.