Media CDN and Image Pipeline
Frontend-facing image/media pipeline design — upload, derivatives, CDN URLs, formats, and responsive delivery.
- system-design
- interview
- architecture
- cdn
- images
Scope the problem
How media gets from upload → processing → CDN → responsive <img>/video with good LCP and cost control.
In scope: client upload UX boundaries, URL design, transforms, caching, formats.
Out of scope: building a codec company.
Pipeline overview
Client upload → object storage (S3)
→ processing worker (resize, strip EXIF, virus scan)
→ derivatives / on-the-fly transform edge
→ CDN
→ browser (srcset / video)
Upload (frontend contract)
- Request signed URL(s) from API
- PUT bytes direct to storage (not through app server)
- Confirm upload → enqueue processing
- UI shows local preview; swaps to CDN URL when ready
See Upload Large Files UX for multipart/resume.
type CreateUploadResponse = {
uploadId: string;
urls: { partNumber: number; url: string }[];
};
Derivative strategies
| Approach | Pros | Cons |
|---|---|---|
| Pre-generate sizes | predictable | storage × variants |
| On-the-fly transform | flexible (?w=800&q=75) |
CPU; need cache |
| Hybrid | common sizes pre; rest on fly | complexity |
URL design:
https://cdn.example.com/i/{imageId}/w/{width}/f/{format}/v/{version}
Immutable version segment → long cache.
Formats & quality
- Negotiate AVIF/WebP/JPEG via
Acceptorf=auto - Quality ladders; don’t ship 95 quality 4k to mobile
- Strip EXIF for privacy (GPS)
- Animated: GIF → muted MP4/WebM for size
Responsive delivery (browser)
<img
alt="..."
width="1200"
height="800"
srcset=".../w/400 400w, .../w/800 800w, .../w/1200 1200w"
sizes="(max-width: 768px) 100vw, 600px"
loading="lazy"
decoding="async"
/>
LCP image: no lazy; fetchpriority="high".
CDN caching
| Content | Cache |
|---|---|
| Immutable derivative URL | max-age=31536000, immutable |
| Original | private or short; not hot path |
| Transform miss | origin shield; then cache |
Purge by tag when legal takedown required.
Video specifics
- HLS/DASH manifests + segments on CDN
- Signed URLs / cookies for paid content
- Multiple renditions; player picks (ABR)
- Thumbnails sprite sheets for scrubbing
Frontend performance checklist
- Always width/height or aspect-ratio
- Blurhash/LQIP placeholders
- Don’t download full-res in grids
- Cap concurrent image requests if needed
- Use CDN domain (HTTP/2/3 connection reuse)
Security
- AuthZ on upload and on private media signed URLs
- Short TTL signatures; refresh on 403
- Content-Type validation; don’t execute user SVG inline without sanitize
- Hotlink protection optional
Cost controls
- Max upload size/type
- Rate limit transforms per IP
- Prefer pre-gen for top N traffic images
- Monitor bandwidth by product surface
Tradeoffs
- Pre-gen vs on-the-fly
- Single global CDN vs multi-vendor
- Client-side compression before upload vs quality loss
- Public bucket vs fully signed
Interview close
Direct-to-storage upload → process → immutable CDN URLs with width/format → srcset/sizes on client → long cache → signed private media. Call out LCP and EXIF privacy.
Operational checklist (interview)
When walking a whiteboard, name the handoffs:
- Client validates and requests a session
- Storage receives bytes via signed URL
- Worker derives variants / scans
- CDN serves immutable URLs
- App swaps preview for final
assetId
Call out failure isolation: upload success ≠ media ready. UI must model processing as first-class, not a spinner on the wrong side of the network.
Frontend URL helper
function mediaUrl(
id: string,
opts: { w: number; format?: "auto" | "avif" | "webp" | "jpg"; v?: string }
) {
const f = opts.format ?? "auto";
const v = opts.v ?? "1";
return `https://cdn.example.com/i/${id}/w/${opts.w}/f/${f}/v/${v}`;
}
Keep helpers in a shared package so marketing pages and app shells don’t invent divergent transform params (which fragment CDN caches).
Monitoring
Track transform cache hit ratio, 4xx on signed URLs, p95 upload complete time, and bytes egress by surface (feed vs PDP). Cost spikes often come from missing sizes attributes downloading oversized assets—not from CDN unit price alone.