CDN (classic)
Introduction
Section titled “Introduction”Azure Content Delivery Network (CDN) caches content from an origin, such as a storage account or a web app, at edge locations close to users.
A classic CDN profile (for example the Standard_Microsoft SKU) holds endpoints. Each endpoint has a <name>.azureedge.net host name, one or more origins, optional origin groups and custom domains, and caching, compression and delivery rules. For more information, see What is a content delivery network on Azure?.
Azure no longer allows new classic CDN profiles, and recommends Azure Front Door instead. LocalStack for Azure supports classic CDN so that you can keep developing and testing existing infrastructure that uses it locally, including the migration of a classic profile to Front Door. The supported APIs are available on our API Coverage section, which provides information on the extent of classic CDN’s integration with LocalStack.
Getting started
Section titled “Getting started”This guide is designed for users new to classic Azure CDN and assumes basic knowledge of the Azure CLI and our lstk az proxy.
Like Azure, LocalStack refuses to create new classic CDN profiles and endpoints by default: the requests fail with a 400 error that says classic creation is no longer supported.
Start LocalStack with CDN_CLASSIC_ALLOW_CREATE=1 to allow it.
Without the flag, reading, deleting and patching existing classic resources (as az cdn profile update and az cdn endpoint update do) still works, but a PUT over an existing classic profile or endpoint, which ARM templates, Bicep and Terraform send when they redeploy, is refused as well.
Launch LocalStack using your preferred method, with CDN_CLASSIC_ALLOW_CREATE=1 set. For more information, see Introduction to LocalStack for Azure. Once the container is running, enable Azure CLI interception by running:
lstk az start-interceptionThis command points the az CLI away from the public Azure management REST API and toward the LocalStack for Azure emulator API.
To revert this configuration, run:
lstk az stop-interceptionThis reconfigures the az CLI to send commands to the official Azure management REST API.
Create a resource group
Section titled “Create a resource group”Create a resource group to hold all resources created in this guide:
az group create \ --name rg-cdn-demo \ --location westeuropeCreate a CDN profile
Section titled “Create a CDN profile”Create a classic profile with the Standard_Microsoft SKU:
az cdn profile create \ --name cdn-profile-demo \ --resource-group rg-cdn-demo \ --sku Standard_Microsoft{ "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-cdn-demo/providers/Microsoft.Cdn/profiles/cdn-profile-demo", "kind": "cdn", "location": "Global", "name": "cdn-profile-demo", "originResponseTimeoutSeconds": 30, "provisioningState": "Succeeded", "resourceGroup": "rg-cdn-demo", "resourceState": "Active", "sku": { "name": "Standard_Microsoft" }, "tags": {}, "type": "Microsoft.Cdn/profiles", ...}Create an endpoint
Section titled “Create an endpoint”Create an endpoint that serves content from www.contoso.com, with compression enabled:
az cdn endpoint create \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo \ --origin www.contoso.com \ --origin-host-header www.contoso.com \ --enable-compression true{ "contentTypesToCompress": [ "text/plain", "text/html", "text/css", "text/javascript", "application/x-javascript", "application/javascript", "application/json", "application/xml" ], "customDomains": [], "geoFilters": [], "hostName": "cdn-endpoint-demo.azureedge.net", "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-cdn-demo/providers/Microsoft.Cdn/profiles/cdn-profile-demo/endpoints/cdn-endpoint-demo", "isCompressionEnabled": true, "isHttpAllowed": true, "isHttpsAllowed": true, "location": "Global", "name": "cdn-endpoint-demo", "originGroups": [], "originHostHeader": "www.contoso.com", "origins": [ { "hostName": "www.contoso.com", "httpPort": 80, "httpsPort": 443, "name": "www-contoso-com" } ], "provisioningState": "Succeeded", "queryStringCachingBehavior": "NotSet", "resourceGroup": "rg-cdn-demo", "resourceState": "Running", "tags": {}, "type": "Microsoft.Cdn/profiles/endpoints", "urlSigningKeys": []}The origins you pass inline are created as origin resources of the endpoint:
az cdn origin list \ --endpoint-name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo \ --output tableEnabled HostName HttpPort HttpsPort Name ProvisioningState ResourceGroup ResourceState--------- --------------- ---------- ----------- --------------- ------------------- --------------- ---------------True www.contoso.com 80 443 www-contoso-com Succeeded rg-cdn-demo ActiveUpdate the endpoint
Section titled “Update the endpoint”Change the endpoint’s query string caching behavior:
az cdn endpoint update \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo \ --query-string-caching-behavior BypassCaching{ "hostName": "cdn-endpoint-demo.azureedge.net", "name": "cdn-endpoint-demo", "provisioningState": "Succeeded", "queryStringCachingBehavior": "BypassCaching", "resourceState": "Running", "type": "Microsoft.Cdn/profiles/endpoints", ...}Add a custom domain
Section titled “Add a custom domain”Add a custom domain to the endpoint:
az cdn custom-domain create \ --name www-example \ --endpoint-name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo \ --hostname www.example.com{ "customHttpsProvisioningState": "Disabled", "hostName": "www.example.com", "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/rg-cdn-demo/providers/Microsoft.Cdn/profiles/cdn-profile-demo/endpoints/cdn-endpoint-demo/customdomains/www-example", "name": "www-example", "provisioningState": "Succeeded", "resourceGroup": "rg-cdn-demo", "resourceState": "Active", "type": "Microsoft.Cdn/profiles/endpoints/customdomains", ...}Purge content
Section titled “Purge content”Purge cached content by path. Each path must start with /:
az cdn endpoint purge \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo \ --content-paths '/images/*'A path without a leading /, such as --content-paths images, is rejected:
(BadRequest) The content path 'images' must start with '/'.Stop and start the endpoint
Section titled “Stop and start the endpoint”Stop the endpoint and check its state:
az cdn endpoint stop \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo
az cdn endpoint show \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo \ --query resourceState \ --output tsvStoppedStart it again:
az cdn endpoint start \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demoCheck name availability
Section titled “Check name availability”Endpoint host names are unique across all subscriptions. Check whether a name is still available:
az cdn name-exists \ --name cdn-endpoint-demo{ "message": "Name not available", "nameAvailable": false, "reason": "Name is already in use"}Delete the endpoint and the profile
Section titled “Delete the endpoint and the profile”Delete the endpoint and the profile, then list the profiles in the resource group to confirm they were removed:
az cdn endpoint delete \ --name cdn-endpoint-demo \ --profile-name cdn-profile-demo \ --resource-group rg-cdn-demo
az cdn profile delete \ --name cdn-profile-demo \ --resource-group rg-cdn-demo
az cdn profile list \ --resource-group rg-cdn-demo[]Features
Section titled “Features”The classic CDN emulator supports the following features:
- Profiles and endpoints: Create, get, update, list, and delete classic profiles and endpoints. Endpoints get a
<name>.azureedge.nethost name. - Origins, origin groups and custom domains: Manage the origins, origin groups and custom domains of an endpoint. Origins and origin groups passed inline when you create an endpoint become resources of their own.
- Endpoint operations: Start and stop endpoints, purge and load content with path validation, and validate custom domains.
- Custom domain HTTPS: Enable and disable HTTPS on a custom domain.
- Classic CDN WAF policies: Create, get, update, list, and delete
cdnWebApplicationFirewallPolicies, list the managed rule sets, and see which endpoints link to a policy. A policy that an endpoint still uses cannot be deleted. - Quotas: A profile holds up to 25 endpoints and an endpoint up to 20 custom domains; usage is reported by the resource usage operations.
- Name availability: Endpoint names are checked against all subscriptions, as on Azure.
- Migration to Front Door: Check whether a classic profile can be migrated, and migrate it to Azure Front Door Standard/Premium. Each classic endpoint becomes a Front Door endpoint (named
<name>-migratedunless you map it), with an origin group holding its origins and a default route for/*. Custom domains and delivery rules are not carried over. - Edge nodes and optimization types: List the edge nodes and the optimization types a profile supports.
Configuration
Section titled “Configuration”| Variable | Default | Effect |
|---|---|---|
CDN_CLASSIC_ALLOW_CREATE |
unset | Allow creating classic CDN profiles and endpoints, which Azure has refused since 2025-08-15. |
CDN_VALIDATE_PROBE_FETCHES |
unset | Make ValidateProbe fetch the URL. Off by default: the emulator answers EndpointProbeCannotBeRetrieved, which is what Azure answers for a URL only reachable from your machine. |
Limitations
Section titled “Limitations”- No content delivery: Classic endpoints do not serve traffic. Requests to
<name>.azureedge.netare not routed to the origin, so caching, compression, delivery rules and geo-filtering are stored and returned but have no effect. To test request routing and caching locally, use Azure Front Door. - Purge and load content have no effect: Paths are validated, but there is no cache to purge or edge to preload.
- Custom domain validation: A host name validates only when it is already a custom domain of the endpoint. DNS records are not checked.
- Custom domain HTTPS: Enabling HTTPS completes straight away and no certificate is issued.
- WAF policies are not enforced: Classic CDN WAF policies are stored, but no requests are evaluated against them.
- Single sign-on:
GenerateSsoUriis not supported for classic profiles.
API Coverage
Section titled “API Coverage”52 of 52 operations implemented
| Operation ▲ | Implemented ▼ |
|---|