← Back to list

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…

Ahmed Kenawy · 2026-06-25 18:20 · 0 claps · 3.5 min read
#system-design-concepts #android #android-development #mobile
Open on Medium ↗
Wiki topics: 📱 · Mobile Development 🎬 · Film & Television

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