# Azure CDN and Caching Headers

> Chapter 62 of the Courseiva AZ-204 curriculum — https://courseiva.com/learn/az-204/content-delivery-204

**Official objective:** 4.2 — Monitor

## Introduction

When delivering web content to a global audience, slow load times can be mitigated by Azure Content Delivery Network (CDN) and caching headers—a critical topic for the AZ-204 exam. You will learn how to accelerate content delivery globally, configure caching rules, and manage cache invalidation. Expect 5-10% of exam questions to touch on CDN endpoints, caching behaviors, and integration with Azure services. Mastering this topic ensures you can design high-performance, scalable web applications that minimize latency for users worldwide.

## Global Library Network with Speed Couriers

What if a massive library system had a central archive in New York City? When a user in Tokyo requests a rare book, the central library staff must locate the book, package it, and ship it via standard mail, which takes days. To speed things up, the library establishes regional branches in Tokyo, London, Sydney, and other major cities. These branches store frequently requested books. Now, when the Tokyo user requests a popular book, the Tokyo branch can hand it to a local courier immediately. However, the branch must follow strict rules: it can only keep a book for a limited time (like a lease) before returning it to the central archive. Also, if the book's content changes (a new edition), the central archive sends a notice to all branches to discard the old copy. The branch must check this notice before serving the book, or it might give out outdated information. This system reduces shipping time from days to minutes, but requires careful coordination on lease durations, invalidation notices, and handling of rare versus popular requests. The courier service itself is like the CDN's edge server network, delivering content at high speed, while the lease and notice system mirrors caching headers and purge mechanisms.

## Core explanation

### What is Azure CDN and Why Use It?

Azure Content Delivery Network (CDN) is a global network of servers (edge nodes) that cache content from your origin (e.g., Azure Storage, Web App) and serve it to users from the nearest location. This reduces latency, offloads origin traffic, and improves user experience. The exam focuses on understanding CDN profiles, endpoints, caching rules, and how to control caching behavior via HTTP headers.

### How Azure CDN Works Internally

When a user requests a resource (e.g., an image) from a URL that points to a CDN endpoint, the DNS resolves to the nearest edge server (based on the user's IP). The edge server checks its cache:
- If the resource is cached and fresh (not expired), it serves it directly (cache hit).
- If not cached or expired (cache miss), the edge server forwards the request to the origin server, caches the response, and serves it to the user.

The caching behavior is controlled by HTTP headers set by the origin, primarily `Cache-Control` and `Expires`. The CDN also respects `Pragma`, `Last-Modified`, and `ETag` for validation.

### Key Components and Defaults

- **CDN Profile**: A collection of CDN endpoints. You can have multiple profiles (e.g., for different environments).
- **CDN Endpoint**: A specific endpoint like `https://myendpoint.azureedge.net`. Each endpoint has a configuration, including origin, caching rules, and compression settings.
- **Caching Rules**: Can be set at the endpoint level or per path/extension. You can define:
  - **Query string caching**: Ignore, bypass, or cache every unique URL.
  - **Default cache behavior**: Override the origin's `Cache-Control` headers.
- **Default TTL**: If no caching headers are set, the CDN uses a default TTL of 7 days for general web delivery and 1 day for Azure Storage blobs. For Azure CDN Standard from Microsoft (Verizon/Premium), the default is 7 days.
- **Cache purge**: Remove cached content across all edge nodes. You can purge by path, wildcard, or root. Purge propagation takes time (up to 10 minutes for Azure CDN Standard from Microsoft).

### Configuration and Verification

To create a CDN profile and endpoint via Azure CLI:
```bash
az cdn profile create --name MyProfile --resource-group MyRG --sku Standard_Microsoft
az cdn endpoint create --name MyEndpoint --profile-name MyProfile --resource-group MyRG --origin www.example.com
```
To set caching rules:
```bash
az cdn endpoint update --name MyEndpoint --profile-name MyProfile --resource-group MyRG --set deliveryPolicy.rules[0].conditions[0].name=UrlPath --set deliveryPolicy.rules[0].conditions[0].parameters.operator=Equals --set deliveryPolicy.rules[0].conditions[0].parameters.matchValues[0]=/images/*
```

To verify caching headers, use `curl -I`:
```bash
curl -I https://myendpoint.azureedge.net/image.png
```
Look for `Cache-Control: public, max-age=31536000` or `Age: 123` header indicating how long the resource has been cached.

### Interaction with Related Technologies

- **Azure Storage**: When using CDN with a storage account, set the `Cache-Control` header on blobs via Azure CLI or .NET SDK. Default is no caching, but CDN applies its default TTL.
- **Azure App Service**: You can configure caching via `web.config` or application code. The CDN respects those headers.
- **Azure Front Door**: A modern alternative to CDN with additional features like WAF, SSL termination, and traffic acceleration. For exam purposes, know that Front Door can also cache content but uses different rules.
- **Azure Redis Cache**: Not a CDN, but can be used to cache data at the application layer. The exam may compare CDN (static content) vs Redis (dynamic data).

### Caching Headers in Detail

- **Cache-Control**: The primary header. Values include:
  - `public`: Any cache may store.
  - `private`: Only browser cache, not CDN.
  - `no-cache`: Must revalidate with origin.
  - `no-store`: Do not cache at all.
  - `max-age=<seconds>`: Maximum time to cache.
  - `s-maxage=<seconds>`: Overrides max-age for shared caches (like CDN).
- **Expires**: HTTP-date (e.g., `Expires: Wed, 21 Oct 2025 07:28:00 GMT`). If both `Cache-Control: max-age` and `Expires` are present, `max-age` takes precedence.
- **Last-Modified**: The origin sends this; CDN can use it for conditional requests (If-Modified-Since).
- **ETag**: A unique identifier for a version; CDN can use it for If-None-Match.

### Cache Behavior with Query Strings

You can configure how CDN handles query strings:
- **Ignore query string**: Cache a single version regardless of query string. Example: `?v=1` and `?v=2` serve the same cached object.
- **Bypass caching for query string**: Do not cache any URL with query strings.
- **Cache every unique URL**: Treat each query string as a separate cache entry.
- **Standard_Microsoft SKU**: Only supports Ignore or Bypass. For Cache every URL, use Verizon or Akamai SKU.

### Compression

Azure CDN can compress responses (gzip, brotli) to reduce bandwidth. Compression is enabled by default for certain MIME types. You can customize compression settings.

### Geo-filtering

You can allow or block countries based on the request's IP. This is configured per endpoint path.

### Purge and Pre-load

- **Purge**: Clears cache for specified paths. Use `az cdn endpoint purge` with content paths.
- **Pre-load**: Pre-populate cache for specific files. Only available on Azure CDN from Verizon (premium). Not commonly tested.

### Common Pitfalls

- **Cache-Control private**: If origin sends `Cache-Control: private`, CDN will not cache the response. This is a common exam trap.
- **Default TTL**: If no headers, CDN caches for 7 days. This can lead to stale content if not managed.
- **Purge propagation**: Purging is not instantaneous. For Standard Microsoft, it can take up to 10 minutes. For Verizon, up to 2 hours.
- **Query string caching**: If you set Ignore, but your app uses query strings for versioning, users may get wrong versions.

### Exam Tips

- Remember the default TTL values: 7 days for general, 1 day for storage.
- Know the difference between `Cache-Control: public` and `private`.
- Understand that `s-maxage` overrides `max-age` for CDN.
- Be aware that Azure CDN Standard from Microsoft does not support cache every unique URL for query strings.
- Purge is not real-time; plan for propagation delay.
- Geo-filtering is based on country code, not region.

### Step-by-step Configuration Example

1. Create a CDN profile with SKU `Standard_Microsoft`.
2. Create an endpoint pointing to your Azure Web App.
3. Set caching rules: for `/static/*`, set override to `public, max-age=604800`.
4. Enable compression for `.css`, `.js`.
5. Purge the root after deploying new version.
6. Test with `curl -I` to verify headers.

## Real-world context

### Scenario 1: Global E-commerce Website

An e-commerce company with users worldwide uses Azure CDN to serve product images, CSS, and JavaScript. The origin is an Azure App Service in the US East region. Without CDN, users in Asia experience 200-300ms latency. With CDN, latency drops to 20-30ms. They configure caching rules: images are cached for 30 days (`Cache-Control: public, max-age=2592000`), CSS/JS for 7 days, and HTML for 1 hour (since product prices change frequently). They also enable query string caching for versioned files (e.g., `style.css?v=2`). A common problem: after a product image update, the old image remains cached. They solve this by purging the specific image path after upload. They also use geo-filtering to block access from certain countries due to licensing restrictions.

### Scenario 2: Video Streaming Platform

A video streaming service uses Azure CDN to deliver video chunks (MP4, HLS). The origin is Azure Blob Storage. They set `Cache-Control: public, max-age=86400` on blobs to cache for 24 hours. To handle hot content, they pre-load popular videos during off-peak hours using the pre-load feature (Verizon SKU). They also enable compression for manifest files. A misconfiguration: they initially set `Cache-Control: no-cache` on video files to ensure freshness, but that caused high origin load. They changed to `max-age=3600` with revalidation using `ETag`. They also use purge to invalidate stale content after encoding errors.

### Scenario 3: Software Update Distribution

A software company distributes installer files via Azure CDN. Installers are large (1-2 GB) and rarely change. They set `Cache-Control: public, max-age=31536000` (1 year) and use versioned filenames (e.g., `setup-2.0.exe`). This ensures users always get the correct version. They also enable compression for smaller files. A common issue: when a new version is released, they must purge the old version's path to force cache refresh. They learned to purge before the release to avoid stale downloads. They also use custom domain with HTTPS to secure downloads.

## Exam focus

### Exactly What AZ-204 Tests

Objective 4.2: "Monitor and optimize Azure solutions". Questions on CDN focus on:
- Configuring caching rules and headers
- Understanding cache behavior (hit/miss, TTL, purge)
- Integrating CDN with Azure Storage and App Service
- Choosing the right SKU based on features
- Troubleshooting stale content

### Common Wrong Answers and Why

1. **Choosing `Cache-Control: private` for CDN caching**: Many think private means only the CDN caches, but actually `private` prevents shared caches (like CDN) from storing the response. The correct header for CDN caching is `public`.
2. **Believing purge is instantaneous**: Candidates often assume purging clears cache immediately. In reality, propagation can take minutes (Standard Microsoft) to hours (Verizon).
3. **Thinking CDN caches dynamic content by default**: CDN is optimized for static content. Dynamic content should use `no-cache` or bypass caching. The exam may present a scenario where dynamic content is served slowly because it's being cached incorrectly.
4. **Confusing Azure CDN with Azure Front Door**: Both cache content, but Front Door is a global load balancer with WAF, while CDN is simpler. The exam expects you to know when to use each.

### Specific Numbers and Terms

- Default TTL: 7 days (general), 1 day (storage).
- Purge propagation: Standard Microsoft up to 10 minutes, Verizon up to 2 hours.
- Query string caching options: Ignore, Bypass, Cache every unique URL (not on Standard Microsoft).
- Compression: enabled by default for text, JavaScript, CSS, JSON.
- Geo-filtering: based on country code.

### Edge Cases and Exceptions

- If origin returns `Cache-Control: no-store`, CDN will not cache at all.
- If both `Cache-Control: max-age` and `Expires` are present, `max-age` takes precedence.
- `s-maxage` overrides `max-age` for shared caches (CDN).
- CDN does not cache responses with `Set-Cookie` header by default.
- For Azure Storage, if no `Cache-Control` is set, CDN uses its default TTL (1 day).

### How to Eliminate Wrong Answers

- If a question asks about caching dynamic content, look for options like "bypass caching" or "use no-cache".
- If a question mentions stale content after update, the solution is purge or reduce TTL.
- If a question involves query strings and CDN SKU, remember Standard Microsoft does not support "Cache every unique URL".
- Always check whether the scenario requires `public` or `private` caching.

## Step by step

1. **Create a CDN Profile** — First, you create a CDN profile, which is a container for endpoints. Choose the SKU based on your needs: Standard_Microsoft for basic features, Standard_Verizon for more advanced rules, or Standard_Akamai for high performance. The profile defines the pricing tier and available features. Use Azure portal, CLI, or PowerShell. Example CLI: `az cdn profile create --name MyProfile --resource-group MyRG --sku Standard_Microsoft`.
2. **Create a CDN Endpoint** — Within the profile, create an endpoint. An endpoint has a unique hostname (e.g., `myendpoint.azureedge.net`) and points to an origin (your web server, storage account, etc.). You specify the origin type (Web App, Storage, Cloud Service) and origin hostname. You can also set custom domain and HTTPS. Example CLI: `az cdn endpoint create --name MyEndpoint --profile-name MyProfile --resource-group MyRG --origin www.example.com`.
3. **Configure Caching Rules** — Set caching behavior to override or respect origin headers. You can define rules based on URL path, extension, or query string. For example, you might set a rule to cache all images for 30 days. The CDN will apply these rules when serving cached content. Use the delivery policy in the endpoint configuration. For CLI, use `az cdn endpoint update` with `--set deliveryPolicy.rules`.
4. **Enable Compression** — Compression reduces file sizes, speeding up delivery. By default, Azure CDN compresses certain MIME types (text, JavaScript, CSS). You can customize the list of file extensions. Enable compression in the endpoint settings. For CLI, use `az cdn endpoint update --name MyEndpoint --profile-name MyProfile --resource-group MyRG --set isCompressionEnabled=true`.
5. **Set Custom Domain and HTTPS** — To use your own domain (e.g., `cdn.example.com`), add a custom domain to the endpoint. Then enable HTTPS by uploading a certificate or using Azure-managed certificates. This ensures secure content delivery. For CLI: `az cdn custom-domain create --endpoint-name MyEndpoint --profile-name MyProfile --resource-group MyRG --hostname cdn.example.com` and `az cdn custom-domain enable-https`.

## Comparisons

### Azure CDN vs Azure Front Door

**Azure CDN:**
- Global content delivery network for caching static content
- Supports multiple origins (Storage, Web App, etc.)
- Caching rules based on path and query string
- No built-in WAF (except with Verizon Premium)
- Pricing based on data transfer and requests

**Azure Front Door:**
- Global load balancer with application layer routing
- Supports multiple backends, health probes, and traffic splitting
- Built-in WAF (Web Application Firewall)
- Supports SSL termination and URL rewrite
- Pricing based on rules and data transfer

## Common misconceptions

- **Misconception:** Cache-Control: private means only the CDN can cache the response. **Reality:** Cache-Control: private means only the browser (private cache) can cache the response; shared caches like CDN must not cache it. To allow CDN caching, use public.
- **Misconception:** Purging the CDN cache is instantaneous. **Reality:** Purge propagation takes time: up to 10 minutes for Standard Microsoft, up to 2 hours for Verizon. Plan accordingly.
- **Misconception:** CDN caches all content by default for 7 days. **Reality:** This is only if the origin does not set any caching headers. If the origin sets Cache-Control headers (e.g., no-cache), the CDN respects them. Also, for Azure Storage, the default is 1 day.
- **Misconception:** Query string caching is the same across all CDN SKUs. **Reality:** Standard Microsoft only supports Ignore and Bypass. To cache every unique URL, you need Verizon or Akamai SKU.
- **Misconception:** CDN automatically compresses all files. **Reality:** Compression is enabled by default only for certain MIME types (text, JavaScript, CSS, JSON). You must configure it for other types.

## Key takeaways

- Default TTL: 7 days for general web delivery, 1 day for Azure Storage.
- Cache-Control: public allows CDN caching; private prevents it.
- Purge propagation can take up to 10 minutes (Standard Microsoft) or 2 hours (Verizon).
- Standard Microsoft CDN does not support 'Cache every unique URL' for query strings.
- s-maxage overrides max-age for shared caches like CDN.
- CDN does not cache responses with Set-Cookie header by default.
- Compression is enabled by default for text, JavaScript, CSS, JSON.

## FAQ

**How do I set Cache-Control headers on Azure Blob Storage for CDN?**

You can set Cache-Control on blobs using Azure CLI: `az storage blob update --account-name <account> --container-name <container> --name <blob> --content-cache-control "public, max-age=3600"`. Alternatively, set it programmatically using the .NET SDK or Azure Storage REST API. If not set, Azure CDN applies a default TTL of 1 day for storage.

**What is the difference between Cache-Control: no-cache and no-store?**

no-cache means the cache must revalidate with the origin before serving the cached copy (using ETag or Last-Modified). no-store means the response must not be stored at all. For CDN, no-cache still allows caching but forces revalidation; no-store prevents caching entirely.

**How long does it take for a CDN purge to take effect?**

For Azure CDN Standard from Microsoft, purge propagation typically completes within 10 minutes. For Azure CDN Standard from Verizon, it can take up to 2 hours. For Akamai, it's usually under a minute. Always test after purge.

**Can Azure CDN cache dynamic content like ASP.NET pages?**

Yes, but you must configure caching headers appropriately. By default, dynamic pages often have no caching headers or are set to private. You can override CDN caching rules to cache dynamic content, but be cautious of stale data. Use short TTLs or revalidation.

**What happens if the origin returns Cache-Control: private?**

Azure CDN will not cache the response. The edge server will forward the request to the origin each time. To allow caching, change the header to public or override the cache behavior in CDN rules.

**How do I enable HTTPS on a custom domain for Azure CDN?**

After adding a custom domain to your CDN endpoint, you can enable HTTPS by selecting 'Custom domain HTTPS' in the portal. You can use Azure-managed certificates (free) or bring your own. The process takes a few minutes.

**What is the difference between Azure CDN and Azure Front Door?**

Azure CDN is primarily for caching static content globally. Azure Front Door is a global load balancer with application acceleration, WAF, and SSL offloading. Front Door can also cache content, but its primary purpose is routing and security. For simple static content delivery, CDN is sufficient and cheaper.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/az-204/content-delivery-204
