Day — 11: CDN & Media Delivery — images, video streaming [System Design]
Two users open your app at the same time. One sees images instantly. The other waits 5 seconds staring at gray boxes. Same app, same code…

Day — 11: CDN & Media Delivery — images, video streaming [System Design]
Two users open your app at the same time. One sees images instantly. The other waits 5 seconds staring at gray boxes. Same app, same code. The difference? How far they are from your server.
The Problem
Your server lives in Germany.
A user in Berlin opens your app — images load instantly.
A user in Cairo opens the same app — images take 5 seconds.
It’s not their internet. It’s not your code. It’s distance. Every image has to travel from Germany to Egypt and back, every single time.
This is the problem a CDN solves.
Think of It Like a Library
Imagine there’s only ONE library in the whole world, and it’s in Germany. Every time anyone wants to read a book, they have to travel to Germany, borrow it, and travel back.
Crazy, right?
Now imagine instead: there’s a copy of that same book in every city’s library. You just walk to the library nearest to you and grab it. Fast. Easy.

That’s a CDN. It keeps copies of your images on servers all around the world, so each user grabs them from the closest one.

What Actually Happens — Cache Hit vs Cache Miss
When a user requests an image, the CDN does one of two things:
Cache Hit — The CDN already has a copy nearby. It hands it over instantly. (5ms)
Cache Miss — The CDN doesn’t have it yet. It fetches it from your main server ONCE, saves a copy, then gives it to the user. The next person nearby gets the saved copy instantly.
So the first user in a region might wait a little. Everyone after them gets it fast.

What a CDN Does for Images
A good CDN doesn’t just copy images — it makes them better automatically:

Android Implementation — Loading CDN Images Right
You don’t build a CDN — you use one (Cloudflare, AWS CloudFront, Bunny, etc.). Your job in Android is to request the right size and let your image library do the rest:
// Ask the CDN for the EXACT size you need — never download a 4000px
// image to show it in a 100px thumbnail
fun ImageView.loadFromCdn(imageId: String, widthPx: Int) {
// CDN resizes on the fly via URL parameters
val url = "https://cdn.myapp.com/images/$imageId?width=$widthPx&format=webp&quality=80"
Glide.with(this)
.load(url)
.diskCacheStrategy(DiskCacheStrategy.ALL) // cache locally too
.placeholder(R.drawable.shimmer) // show while loading
.into(this)
}
// Usage — request size based on where it's shown
thumbnailView.loadFromCdn(post.imageId, widthPx = 200) // small list item
fullImageView.loadFromCdn(post.imageId, widthPx = 1080) // full screen
// For video — stream from CDN instead of downloading the whole file
val player = ExoPlayer.Builder(context).build()
val mediaItem = MediaItem.fromUri("https://cdn.myapp.com/videos/$videoId/master.m3u8")
player.setMediaItem(mediaItem) // HLS streaming — loads in chunks from nearest CDN edge
player.prepare()
Common Mistakes
Mistake 1 — Downloading full-size images for thumbnails
// ❌ Downloading a 4000x3000 image to show in a 100px circle
Glide.with(this).load("https://cdn.myapp.com/photo.jpg").into(avatarView)
// ✅ Ask the CDN to resize it first — 40x smaller download
Glide.with(this).load("https://cdn.myapp.com/photo.jpg?width=100").into(avatarView)
Mistake 2 — Not using the right image format
// ❌ Always serving JPG — bigger files, slower loads
"https://cdn.myapp.com/photo.jpg"
// ✅ Let the CDN serve WebP/AVIF — same quality, much smaller
"https://cdn.myapp.com/photo.jpg?format=webp"
Mistake 3 — Caching images that change often with a long TTL
❌ Profile pictures cached for 1 year — user changes photo, still sees old one
✅ Use short cache for changing content, long cache for permanent content
(add a version: photo.jpg?v=2 forces a fresh fetch when it changes)
Key Takeaways
- A CDN keeps copies of your images on servers worldwide, so each user loads from the nearest one — like a library copy in every city.
- Cache Hit = image is already nearby (fast). Cache Miss = CDN fetches it once from your server, then caches it for everyone after.
- A CDN doesn’t just cache — it resizes, compresses, and converts formats automatically.
- In Android, always request the exact image size you need from the CDN — never download a huge image for a tiny thumbnail.
- Stream videos from a CDN using HLS (.m3u8) with ExoPlayer — it loads in chunks from the nearest edge, not all at once.
AndroidDevelopment #SystemDesign #Kotlin #MobileDevelopment #SoftwareEngineering
메타데이터
- post_id
- 7d18cbc02c6c
- slug
- day-11-cdn-media-delivery-images-video-streaming-system-design-7d18cbc02c6c
- url
- https://medium.com/@a7medsa3dkenawy/day-11-cdn-media-delivery-images-video-streaming-system-design-7d18cbc02c6c
- canonical_url
- https://medium.com/@a7medsa3dkenawy/day-11-cdn-media-delivery-images-video-streaming-system-design-7d18cbc02c6c
- author_url
- https://medium.com/@a7medsa3dkenawy
- status
- ok
- fetched_at
- 2026-06-26 06:47:43