Practice this topic in a realistic system design interview
A Content Delivery Network (CDN) is a distributed network of servers that caches content closer to users.
Suppose your application runs in a data center in Virginia. A user in New York requests an image. That request does not have to travel very far. But now imagine a user in India requesting the same image. The request has to travel across a much longer network path before reaching your server, and that increases latency.
And if millions of users around the world request the same static files, your origin server has to send those files again and again. This is wasteful because the content may be identical for every user.
A CDN solves this by storing copies of popular content in many locations around the world.
Loading simulation...
In this chapter, we will look at how CDNs work, what they cache, how requests are routed, and the trade-offs involved.
CDN servers are deployed in geographic locations close to users. These locations are commonly called edge locations or Points of Presence (PoPs). Each edge location runs servers that can accept user requests, store cached responses, and forward requests to the origin when needed.
Suppose your origin server is in the United States, but your CDN has edge servers in Singapore, Mumbai, London, Tokyo, and many other cities. When a user in India requests an image, the request can be served from a nearby CDN edge instead of traveling all the way to the United States.
The shorter network path usually means lower latency. It also means the origin server does less work, because many requests never reach it.
Suppose a user requests an image called logo.png. The request is routed to a nearby CDN edge server, and the CDN checks whether it already has the image.
Now the next user in that region requesting the same image can receive it directly from the edge. This is essentially caching at a global scale.
The origin is the authoritative source from which the CDN retrieves content. It might be an application server, an object storage service, or another backend system such as a load balancer or API gateway.
For example, a website may store images and videos in object storage. The CDN sits in front of that storage. Users request content from the CDN, and the CDN only contacts the origin when it does not already have the required object or when its cached copy has expired.
This protects the origin from having to serve every request directly. It no longer serves every image, JavaScript file, or video segment. It mostly handles misses, dynamic requests, writes, and content that should not be cached.
CDNs are commonly used for static content. This includes images, JavaScript files, CSS files, fonts, videos, software downloads, and other files that do not change on every request. These are good candidates because the same content may be requested millions of times.
Modern CDNs can also cache some dynamic content. For example, a product page or an API response may be cacheable if the same response is safe to reuse across users.
The important question is whether different requests can share the same cached response. If the content is highly personalized, caching it becomes much more difficult.
A good fit for CDN caching is content that:
Poor fits include account pages, shopping carts, payment flows, admin pages, and responses that depend on private cookies or login state.
The origin usually tells the CDN how content should be cached using HTTP caching headers. One of the most important is Cache-Control.
For example, an origin might tell the CDN that an image can be cached for one hour. During that hour, the edge can serve the cached copy without contacting the origin. After the cache lifetime expires, the CDN may need to validate or fetch the content again.
These headers let the application control freshness. Static assets may be cached for a long time. More dynamic data may have a much shorter lifetime.
The directives you will see most often:
max-age, but only for shared caches such as CDNs.ETag and Last-Modified help with validation. When a cached copy expires, the CDN can ask the origin whether the object changed. If it did not, the origin returns a small 304 Not Modified response instead of sending the full object again.
Like any cache, CDN entries usually have a TTL. The TTL defines how long the CDN can reuse a cached object before considering it expired.
So the same caching trade-off applies. The correct TTL depends on how often the content changes and how much staleness users can tolerate. For versioned JavaScript files, the TTL may be very long. For frequently changing API responses, it may be only a few seconds or minutes.
Sometimes you cannot wait for the TTL to expire. Suppose you accidentally publish the wrong image and need to replace it immediately. The old version may already exist in CDN caches around the world.
One option is to purge, or invalidate, the cached object. The CDN removes or stops serving the old copy, and the next request fetches the updated version from the origin.
Many CDNs let you purge a single URL, a path prefix, or a group of objects tagged together. But global invalidation can take time, providers limit how much you can purge, and every purged object turns into a miss that goes back to the origin. A large purge can create a burst of origin traffic.
That is why many systems prefer versioned file names. Instead of replacing logo.png, they publish something like logo.v2.png. The new URL creates a new cache entry.
Versioned URLs are especially useful for static assets. Suppose your application uses app.js. If you replace the file but keep the same URL, some users may continue receiving the old cached version.
Instead, the build system can generate a new file name whenever the content changes, such as app.a7b9.js. When the file changes, the hash changes, and the new deployment references a completely different URL.
The CDN can cache each version for a very long time because the content at that URL never changes. This gives you both strong caching and reliable updates.
For content that has to keep the same URL, such as an HTML page, use a short TTL, purge when it changes, or rely on ETag validation.
A CDN only helps if users are routed to a nearby, healthy edge location. This routing can happen in different ways.
The exact mechanism varies by CDN provider, and the closest edge on a map is not always the one chosen. Network speed, edge capacity, and server health also play a part. But the goal is the same: send the user to an edge that can serve the request efficiently.
There are two ways content can get into the edge.
With a pull CDN, content is loaded into the edge only when someone requests it.
Suppose an image has never been requested from an edge in Tokyo. The first request becomes a cache miss. The Tokyo edge fetches the image from the origin and stores it. Later requests become cache hits.
This is simple because you do not need to push every file to every location ahead of time. The downside is that the first request in a region experiences higher latency.
With a push CDN, the application uploads content to the CDN before users request it. The CDN distributes that content across its network.
This can be useful when you know exactly which files need to be available. For example, large software downloads or media files may be distributed ahead of a launch.
Push CDNs can avoid the first-request miss. But they require more coordination, because the application has to explicitly manage what content is uploaded and when it changes.
In practice, pull-based caching is more common for general web content.
Large CDN deployments sometimes add another cache layer between edge servers and the origin. This is often called an origin shield.
Suppose one hundred edge locations all miss the same popular object. Without a shield, all one hundred may request it from the origin. With an origin shield, those edge servers request the object from an intermediate cache, and the shield may fetch it from the origin only once.
This reduces duplicate origin requests. It is especially useful when many edge locations need the same content at roughly the same time.
CDNs can experience cache stampedes just like application caches. Suppose a very popular object expires at many edge locations around the same time. Many edges may then request the same object from the origin, which can create a large traffic spike.
Several techniques reduce this problem:
For example, with stale-while-revalidate an edge can continue serving the old copy while it refreshes in the background. That protects the origin from a sudden burst.
CDNs work best when many users can share the same cached response. Personalized content makes this harder.
Suppose an API response includes the current user's name and account information. You cannot safely serve that same cached response to another user.
You could include user-specific information in the cache key, but then every user gets a different entry, which reduces the value of caching. So systems often separate shared content from personalized content. The CDN serves common assets and public data, while personalized requests continue to the application backend.
Do not cache private user data in a shared CDN cache unless the design has been reviewed carefully. A small mistake can show one user's data to another user.
Just like any cache, a CDN needs a cache key. The cache key decides whether two requests should use the same cached response.
The URL is usually part of the key. But query parameters, headers, cookies, or other request attributes may also matter.
Suppose the first two requests return exactly the same image. If the CDN treats every query parameter as part of the key, it stores two copies of the same object, and the hit ratio drops. This is a key that is too narrow. Including every cookie in the key causes the same problem, since almost every request then looks unique.
But if a query parameter genuinely changes the response, like the width in the last two requests, ignoring it would return the wrong content. This is a key that is too broad. Ignoring a language header, for example, could send English content to a user who asked for Spanish.
So CDN cache key design is an important part of getting a good hit ratio without serving incorrect responses. Most CDNs let you choose which query parameters, headers, and cookies go into the key. Keep it small for public content, and leave cookies out unless the response really depends on them.
CDNs are not limited to images and JavaScript. Some API responses can also be cached at the edge.
Suppose a public API returns the current list of supported countries. Every user receives the same response, and the data changes rarely. That response can be cached globally.
Now requests can be answered from nearby edges without reaching the application servers. This reduces both latency and backend load.
But APIs need careful cache rules. If a response depends on authentication, cookies, language, location, or other request data, the cache key and privacy rules must reflect that. Endpoints like /api/me or /checkout should usually skip the shared cache entirely.
CDNs are especially useful for large files such as videos, downloads, and software packages. Serving a one-gigabyte file repeatedly from a single origin can consume a large amount of bandwidth. With a CDN, popular files are served from edge infrastructure instead.
CDNs can also support range requests. A client can request only part of a file instead of downloading the entire object.
This is useful for video streaming, where users may jump to different points in a video. The CDN can serve the requested byte ranges without forcing the origin to handle every stream directly.
A CDN can also improve reliability. If the origin becomes temporarily unavailable, some CDNs can continue serving cached content. This may keep static parts of the application working even during backend problems.
The CDN also absorbs a large amount of normal traffic before it reaches your infrastructure. This reduces bandwidth usage and connection load on the origin, and it helps during product launches, sales, and other traffic spikes.
Many CDN platforms also provide protection against denial-of-service attacks, along with web application firewall rules, bot filtering, rate limits, and TLS management. These reduce how much unwanted traffic reaches the origin, but they do not replace application security.
A CDN should not be treated as a replacement for a reliable backend. If content is not cached, requests still need to reach the origin.
Several metrics help determine whether a CDN is working effectively.
A high overall hit ratio can hide a bad path, so check the hit ratio for the routes that matter most to users and to your origin cost.
When debugging, response headers tell you what the CDN did with a request:
Age shows how many seconds the cached copy has been stored, and a header like X-Cache shows whether the request was a hit or a miss. The exact header names vary by provider.
Major CDN providers include:
Choose a provider based on your system's needs. Useful things to compare include where your users are, how well it fits your cloud, how flexible the cache rules are, how fast purges are, origin shielding and request coalescing support, logs and metrics, security features, and pricing for your traffic pattern. CDN pricing often includes bandwidth, request count, purges, and extra features, and video or large downloads can become expensive.
For example, a team already running on AWS may prefer CloudFront because it fits naturally with the rest of their stack. A media company may care more about video delivery features.
A Content Delivery Network is essentially a globally distributed caching layer. It stores content at edge locations closer to users. When the content is already cached, the edge can serve it without contacting the origin.
This reduces latency, lowers origin load, and helps systems handle traffic from users around the world. CDNs work especially well for static assets, large files, and shared API responses.
But you still need to think about:
10 quizzes