# Azure Front Door

<Image
  src={azureIcon}
  alt="Azure Front Door logo"
  height={80}
  width={80}
  class:list={'float-inline-left icon'}
  data-zoom-off
/>

[Azure Front Door](https://learn.microsoft.com/azure/frontdoor/) is a global, scalable entry point that uses Microsoft's edge network to deliver fast, secure, and highly available web applications. The Aspire Azure Front Door hosting integration provisions a Front Door profile and routes traffic to your backends.

## Hosting integration

The Aspire Azure Front Door hosting integration models the resource as the following type:

- `AzureFrontDoorResource`: Represents an Azure Front Door profile, including its endpoints, origin groups, origins, and routes.

To access this type and APIs, add the [📦 Aspire.Hosting.Azure.FrontDoor](https://www.nuget.org/packages/Aspire.Hosting.Azure.FrontDoor) NuGet package to your AppHost project.

<InstallPackage packageName="Aspire.Hosting.Azure.FrontDoor" />

### Add an Azure Front Door resource

In your AppHost, call `AddAzureFrontDoor` to add a Front Door profile, then call `WithOrigin` to attach a backend resource as an origin:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("production");

var api = builder.AddProject<Projects.Api>("api")
    .WithExternalHttpEndpoints();

builder.AddAzureFrontDoor("frontdoor")
    .WithOrigin(api);

// After adding all resources, run the app...
builder.Build().Run();
```

The preceding code:

- Adds an Azure App Service environment (a compute environment is required so Front Door can resolve the origin's hostname).
- Adds an `api` project and exposes it externally with `WithExternalHttpEndpoints`. Front Door requires an origin to expose an external HTTP or HTTPS endpoint.
- Adds a Front Door profile named `frontdoor` and configures the `api` project as an origin.

Each call to `WithOrigin` creates a separate Front Door endpoint, origin group, origin, and route, so each backend is independently routable through its own `*.azurefd.net` hostname.
**Caution:** When you call `AddAzureFrontDoor`, it implicitly calls
  `AddAzureProvisioning`—which adds support for generating Azure resources
  dynamically during app startup. The app must configure the appropriate
  subscription and location. For more information, see [Local provisioning:
  Configuration](/integrations/cloud/azure/local-provisioning/#configuration).

### Add multiple origins

You can add multiple backends to the same Front Door profile. Each origin gets its own Front Door endpoint and route:

```csharp title="C# — AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("production");

var api = builder.AddProject<Projects.Api>("api")
    .WithExternalHttpEndpoints();

var web = builder.AddProject<Projects.Web>("web")
    .WithExternalHttpEndpoints();

builder.AddAzureFrontDoor("frontdoor")
    .WithOrigin(api)
    .WithOrigin(web);

builder.Build().Run();
```

Each origin must be added at most once per Front Door resource — adding the same resource twice throws `InvalidOperationException`.

### Health probes

Front Door uses health probes to determine which origins are healthy. By default, the Aspire integration probes the origin's external endpoint at path `/` over HTTPS. If you have configured an HTTP probe on the origin (for example with `WithHttpProbe`), Front Door uses the path and protocol from the resource's liveness probe instead.

### Provisioning-generated Bicep

When you publish your app, Aspire generates Bicep alongside the manifest. A Front Door resource with a single origin generates Bicep similar to the following:

```bicep title="Generated Bicep — frontdoor.bicep"
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location

param my_api_host string

resource frontdoor 'Microsoft.Cdn/profiles@2025-06-01' = {
  name: take('frontdoor-${uniqueString(resourceGroup().id)}', 90)
  location: 'Global'
  sku: {
    name: 'Standard_AzureFrontDoor'
  }
  tags: {
    'aspire-resource-name': 'frontdoor'
  }
}

resource my_apiEndpoint 'Microsoft.Cdn/profiles/afdEndpoints@2025-06-01' = {
  name: take('my-api-${uniqueString(resourceGroup().id)}', 46)
  location: 'Global'
  parent: frontdoor
}

resource my_apiOriginGroup 'Microsoft.Cdn/profiles/originGroups@2025-06-01' = {
  name: take('my-api-og-${uniqueString(resourceGroup().id)}', 90)
  properties: {
    healthProbeSettings: {
      probePath: '/'
      probeProtocol: 'Https'
    }
    loadBalancingSettings: {
      sampleSize: 4
      successfulSamplesRequired: 3
      additionalLatencyInMilliseconds: 50
    }
  }
  parent: frontdoor
}

resource my_apiOrigin 'Microsoft.Cdn/profiles/originGroups/origins@2025-06-01' = {
  name: take('my-api-origin-${uniqueString(resourceGroup().id)}', 90)
  properties: {
    hostName: my_api_host
    originHostHeader: my_api_host
  }
  parent: my_apiOriginGroup
}

resource my_apiRoute 'Microsoft.Cdn/profiles/afdEndpoints/routes@2025-06-01' = {
  name: take('my-api-route-${uniqueString(resourceGroup().id)}', 90)
  properties: {
    forwardingProtocol: 'HttpsOnly'
    httpsRedirect: 'Enabled'
    linkToDefaultDomain: 'Enabled'
    originGroup: {
      id: my_apiOriginGroup.id
    }
    patternsToMatch: [
      '/*'
    ]
  }
  parent: my_apiEndpoint
  dependsOn: [
    my_apiOrigin
  ]
}

output my_api_endpointUrl string = 'https://${my_apiEndpoint.properties.hostName}'
```

Aspire passes the origin's hostname (resolved from the compute environment, not the full URL) into the `my_api_host` parameter so the Front Door origin points at the deployed backend.

The generated Bicep is a starting point and is influenced by changes to the provisioning infrastructure in C#. Customizations to the Bicep file directly are overwritten, so make changes through the C# provisioning APIs to ensure they're reflected in the generated files.

#### Customize provisioning infrastructure

For advanced scenarios such as upgrading to the Premium SKU, attaching a Web Application Firewall (WAF) policy, configuring caching, or tuning routes, use `ConfigureInfrastructure` to modify the generated Bicep model directly:

```csharp title="C# — AppHost.cs"
using Azure.Provisioning.Cdn;

var frontDoor = builder.AddAzureFrontDoor("frontdoor")
    .WithOrigin(api)
    .ConfigureInfrastructure(infra =>
    {
        var resources = infra.GetProvisionableResources();

        // Upgrade to Premium SKU (required for WAF).
        var profile = resources.OfType<CdnProfile>().Single();
        profile.SkuName = CdnSkuName.PremiumAzureFrontDoor;

        // Enable caching on the route.
        var route = resources.OfType<FrontDoorRoute>().Single();
        route.CacheConfiguration = new FrontDoorRouteCacheConfiguration
        {
            QueryStringCachingBehavior = FrontDoorQueryStringCachingBehavior.IgnoreQueryString
        };
    });
```

For more information, see [Customize Azure resources](/integrations/cloud/azure/customize-resources/). For the full list of configurable properties, see the [Azure.Provisioning.Cdn](https://learn.microsoft.com/dotnet/api/azure.provisioning.cdn) and [Azure.Provisioning.FrontDoor](https://learn.microsoft.com/dotnet/api/azure.provisioning.frontdoor) API documentation.

## See also

- [Azure Front Door documentation](https://learn.microsoft.com/azure/frontdoor/)
- [Azure Front Door tier comparison](https://learn.microsoft.com/azure/frontdoor/standard-premium/tier-comparison)
- [Azure App Service integration](/integrations/cloud/azure/azure-app-service/azure-app-service-host/)
- [Azure integration overview](/integrations/cloud/azure/overview/)