Skip to content

πŸš€ End-to-End Tutorial: Azure Blob Storage + Azure Front Door CDN for Website Assets

πŸ“Œ Use Case

You have:

  • A frontend website hosted in Azure App Service
  • Static assets like:

  • Images (.png, .jpg, .webp)

  • Videos (.mp4)
  • JS/CSS files

You want:

βœ… CDN caching βœ… Faster global delivery βœ… Reduced load on App Service βœ… Best practice Azure architecture


πŸ— Recommended Architecture

Users
   ↓
Azure Front Door (CDN + Edge Cache)
   ↓
Azure Blob Storage (Assets Container)

Frontend Website
   ↓
Azure App Service

βœ… Why Use Blob + Front Door?

App Service is meant for:

  • Hosting frontend/backend apps
  • Running server logic

Blob Storage is meant for:

  • Cheap static storage
  • Large media files
  • Unlimited scaling

Front Door provides:

  • Global CDN edge caching
  • HTTPS support
  • Custom domain support
  • WAF security (optional)

βœ… Step 1: Create Blob Storage for Assets

1. Storage Account

If Storage Account already exists, reference it:

data "azurerm_storage_account" "assets_sa" {
  name                = var.storage_account_name
  resource_group_name = var.resource_group_name
}

2. Create Container for Assets

resource "azurerm_storage_container" "assets_container" {
  name                  = "assets"
  storage_account_name  = data.azurerm_storage_account.assets_sa.name
  container_access_type = "blob"
}

Now your assets will be stored like:

https://<storage-account>.blob.core.windows.net/assets/logo.png

βœ… Step 2: Create Azure Front Door Profile

Front Door Profile is the main CDN service.

resource "azurerm_cdn_frontdoor_profile" "cdn_profile" {
  name                = var.frontdoor_profile_name
  resource_group_name = var.resource_group_name

  sku_name = "Standard_AzureFrontDoor"
}

Example:

frontdoor_profile_name = "assets-cdn-profile"

βœ… Step 3: Create Front Door Endpoint

Endpoint gives you the CDN URL:

https://<endpoint>.azurefd.net

Terraform:

resource "azurerm_cdn_frontdoor_endpoint" "cdn_endpoint" {
  name                     = var.frontdoor_endpoint_name
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.cdn_profile.id
}

Example:

frontdoor_endpoint_name = "assets-cdn-endpoint"

βœ… Step 4: Configure Origin Group

Origin Group manages backend health + load balancing.

resource "azurerm_cdn_frontdoor_origin_group" "origin_group" {
  name                     = var.origin_group_name
  cdn_frontdoor_profile_id = azurerm_cdn_frontdoor_profile.cdn_profile.id

  load_balancing {
    sample_size                 = 4
    successful_samples_required = 3
  }
}

Example:

origin_group_name = "blob-assets-origin-group"

βœ… Step 5: Add Blob Storage as Origin

Front Door Origin = Blob Storage endpoint.

resource "azurerm_cdn_frontdoor_origin" "blob_origin" {
  name                          = var.origin_name
  cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id

  enabled                        = true
  host_name                      = data.azurerm_storage_account.assets_sa.primary_blob_host
  origin_host_header             = data.azurerm_storage_account.assets_sa.primary_blob_host
  certificate_name_check_enabled = true

  http_port  = 80
  https_port = 443

  priority = 1
  weight   = 100
}

Example:

origin_name = "blob-storage-origin"

βœ… Step 6: Create Front Door Route (Container Mapping)

Azure Front Door does not directly know the container name.

So you must route requests like:

/assets/*

Terraform:

resource "azurerm_cdn_frontdoor_route" "assets_route" {
  name                          = var.route_name
  cdn_frontdoor_endpoint_id     = azurerm_cdn_frontdoor_endpoint.cdn_endpoint.id
  cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id

  cdn_frontdoor_origin_ids = [
    azurerm_cdn_frontdoor_origin.blob_origin.id
  ]

  enabled = true

  patterns_to_match = [
    "/${azurerm_storage_container.assets_container.name}/*"
  ]

  supported_protocols = ["Http", "Https"]
  forwarding_protocol = "HttpsOnly"

  link_to_default_domain = true

  cache {
    compression_enabled           = false
    query_string_caching_behavior = "IgnoreQueryString"
  }
}

Example:

route_name = "assets-cdn-route"

βœ… Step 7: Deploy Terraform

Run:

terraform init
terraform plan
terraform apply

βœ… Step 8: Upload Assets to Blob

Example upload:

az storage blob upload \
  --account-name <storage-account-name> \
  --container-name assets \
  --name images/logo.png \
  --file ./logo.png

βœ… Step 9: Access Assets Through CDN

Blob URL:

https://<storage-account>.blob.core.windows.net/assets/images/logo.png

Front Door CDN URL:

https://assets-cdn-endpoint.azurefd.net/assets/images/logo.png

Now assets are served globally from edge cache πŸŽ‰


βœ… Step 10: Use CDN in App Service Frontend

In your frontend code:

<img src="https://assets-cdn-endpoint.azurefd.net/assets/images/logo.png" />

For videos:

<video controls>
  <source src="https://assets-cdn-endpoint.azurefd.net/assets/videos/demo.mp4" />
</video>

⭐ Production Improvements (Next Step)

To make this enterprise-ready:

βœ… Custom domain: cdn.yoursite.com βœ… Private Blob + Origin Access Control βœ… Cache TTL rules (30 days) βœ… WAF protection


βœ… Final Result

You implemented a scalable CDN architecture:

  • Frontend hosted on App Service
  • Assets stored in Blob Storage
  • Azure Front Door providing CDN caching globally

This is the best practice setup in Azure today.


βœ… CDN Setup for Other Azure Services

Azure has one main modern CDN platform now:

⭐ Azure Front Door (Standard/Premium)

Front Door can sit in front of:

  • Blob Storage
  • App Service
  • Static Web Apps
  • AKS Ingress
  • API Management
  • Any public HTTP backend

βœ… Best CDN Options by Service


1️⃣ App Service + Front Door CDN (Full Website Acceleration)

If you want CDN for your full frontend site:

Users β†’ Front Door β†’ App Service

Use Case:

  • Global website performance
  • Custom domain + SSL
  • WAF protection

Terraform origin becomes App Service host:

resource "azurerm_cdn_frontdoor_origin" "app_origin" {
  name                          = "appservice-origin"
  cdn_frontdoor_origin_group_id = azurerm_cdn_frontdoor_origin_group.origin_group.id

  host_name          = azurerm_linux_web_app.frontend.default_hostname
  origin_host_header = azurerm_linux_web_app.frontend.default_hostname

  https_port = 443
}

Then route:

patterns_to_match = ["/*"]

2️⃣ Azure Static Web Apps (Built-in CDN)

Static Web Apps already includes global distribution.

So no extra CDN needed if:

βœ… Fully static React/Vue frontend

URL:

https://yourapp.azurestaticapps.net

Best for:

  • Static sites
  • Jamstack apps

3️⃣ AKS + Front Door CDN (Kubernetes Workloads)

If your frontend/backend runs in AKS:

Users β†’ Front Door β†’ AKS Ingress Controller

Origin is Ingress public IP / DNS:

host_name = "myaks-ingress.mydomain.com"

Best for:

  • Microservices
  • Global traffic routing

4️⃣ API Management + Front Door

For APIs:

Users β†’ Front Door β†’ API Management β†’ Backend

Benefits:

  • API caching
  • WAF protection
  • Global routing

Origin:

host_name = azurerm_api_management.apim.gateway_url

5️⃣ Azure Storage (Blob, Static Website, Files)

Blob is the most common CDN backend.

Best for:

  • Images
  • Videos
  • Downloads

6️⃣ Azure Container Apps + Front Door

Container Apps provide a public endpoint.

Users β†’ Front Door β†’ Container App

Origin host:

host_name = azurerm_container_app.app.latest_revision_fqdn

7️⃣ Azure VM / NGINX + Front Door

If you have a VM running a website:

Users β†’ Front Door β†’ VM Public IP/DNS

Origin:

host_name = "vm-web.mydomain.com"

πŸ”₯ One Front Door, Multiple Origins (Best Practice)

You can configure:

  • /assets/* β†’ Blob Storage
  • /api/* β†’ API Management
  • /* β†’ App Service frontend

Example routing:

Path Pattern Backend
/assets/* Blob Storage
/api/* API Management
/* App Service

That’s the most scalable production setup.


⭐ Recommended Setup for You

Since you already have:

βœ… App Service frontend βœ… Blob assets CDN

Next best:

Add App Service itself behind Front Door

So users access:

https://www.yoursite.com

And assets load from:

https://cdn.yoursite.com/assets/...