DeployU
Interviews / Cloud & DevOps / Design a global application with Azure Front Door for traffic management and WAF protection.

Design a global application with Azure Front Door for traffic management and WAF protection.

architecture Traffic Management Interactive Quiz Code Examples

The Scenario

Your e-commerce platform needs global reach:

Current State:
├── Single region: East US
├── Average latency: 200ms (US), 400ms (Europe), 600ms (Asia)
├── No CDN for static assets
├── Single origin = single point of failure
└── Compliance: GDPR requires EU data to stay in EU

Business Requirements:
├── < 100ms latency globally for static content
├── < 200ms latency for API responses
├── 99.99% availability (multi-region)
├── Automatic failover between regions
└── WAF protection against OWASP Top 10

The Challenge

Design a multi-region architecture using Azure Front Door Premium with intelligent traffic routing, WAF protection, and private link to origins.

Wrong Approach

A junior engineer might deploy Traffic Manager for HTTP workloads, use Application Gateway per region without global load balancing, configure round-robin routing ignoring latency, or expose backend services publicly. These approaches add latency, don't provide edge caching, or create security risks.

Right Approach

A senior engineer uses Azure Front Door Premium for global HTTP load balancing with built-in CDN, configures latency-based routing, enables WAF with managed rule sets, uses Private Link for secure origin connections, and implements proper caching rules.

Architecture Overview

                           Azure Front Door Premium
                    ┌──────────────────────────────────────┐
                    │         Global Entry Point           │
                    │     app.contoso.com (Anycast)        │
                    │                                       │
                    │  ┌─────────────────────────────────┐ │
                    │  │           WAF Policy             │ │
                    │  │  OWASP 3.2 + Custom Rules        │ │
                    │  └─────────────────────────────────┘ │
                    │                                       │
                    │  ┌─────────────────────────────────┐ │
                    │  │     CDN / Edge Caching          │ │
                    │  │  Static: /images/*, /css/*      │ │
                    │  └─────────────────────────────────┘ │
                    └──────────────────────────────────────┘

                    ┌─────────────────┼─────────────────┐
                    ▼                 ▼                 ▼
          ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
          │   East US       │ │   West Europe   │ │   Southeast Asia│
          │                 │ │                 │ │                 │
          │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
          │ │App Service  │ │ │ │App Service  │ │ │ │App Service  │ │
          │ │(Private EP) │ │ │ │(Private EP) │ │ │ │(Private EP) │ │
          │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
          │                 │ │                 │ │                 │
          │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │
          │ │  Azure SQL  │ │ │ │  Azure SQL  │ │ │ │  Azure SQL  │ │
          │ │  (Read Rep) │ │ │ │  (Primary)  │ │ │ │  (Read Rep) │ │
          │ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │
          └─────────────────┘ └─────────────────┘ └─────────────────┘

Step 1: Create Front Door Profile

// Azure Front Door Premium with WAF and Private Link
resource frontDoorProfile 'Microsoft.Cdn/profiles@2023-05-01' = {
  name: 'fd-contoso-global'
  location: 'global'
  sku: {
    name: 'Premium_AzureFrontDoor'  // Required for Private Link and WAF
  }
}

// Custom domain endpoint
resource frontDoorEndpoint 'Microsoft.Cdn/profiles/afdEndpoints@2023-05-01' = {
  parent: frontDoorProfile
  name: 'contoso-endpoint'
  location: 'global'
  properties: {
    enabledState: 'Enabled'
  }
}

// Custom domain
resource customDomain 'Microsoft.Cdn/profiles/customDomains@2023-05-01' = {
  parent: frontDoorProfile
  name: 'app-contoso-com'
  properties: {
    hostName: 'app.contoso.com'
    tlsSettings: {
      certificateType: 'ManagedCertificate'
      minimumTlsVersion: 'TLS12'
    }
  }
}

Step 2: Configure Origin Groups with Health Probes

// Origin group for multi-region backends
resource originGroup 'Microsoft.Cdn/profiles/originGroups@2023-05-01' = {
  parent: frontDoorProfile
  name: 'app-origin-group'
  properties: {
    loadBalancingSettings: {
      sampleSize: 4
      successfulSamplesRequired: 2
      additionalLatencyInMilliseconds: 50  // Latency tolerance
    }
    healthProbeSettings: {
      probePath: '/health'
      probeRequestType: 'GET'
      probeProtocol: 'Https'
      probeIntervalInSeconds: 30
    }
    sessionAffinityState: 'Disabled'  // Enable if needed for stateful apps
  }
}

// East US origin (App Service with Private Link)
resource originEastUS 'Microsoft.Cdn/profiles/originGroups/origins@2023-05-01' = {
  parent: originGroup
  name: 'origin-eastus'
  properties: {
    hostName: 'app-eastus.azurewebsites.net'
    httpPort: 80
    httpsPort: 443
    originHostHeader: 'app-eastus.azurewebsites.net'
    priority: 1
    weight: 1000
    enabledState: 'Enabled'
    sharedPrivateLinkResource: {
      privateLink: {
        id: appServiceEastUS.id
      }
      groupId: 'sites'
      privateLinkLocation: 'eastus'
      requestMessage: 'Front Door Private Link'
    }
  }
}

// West Europe origin
resource originWestEurope 'Microsoft.Cdn/profiles/originGroups/origins@2023-05-01' = {
  parent: originGroup
  name: 'origin-westeurope'
  properties: {
    hostName: 'app-westeurope.azurewebsites.net'
    httpPort: 80
    httpsPort: 443
    originHostHeader: 'app-westeurope.azurewebsites.net'
    priority: 1
    weight: 1000
    enabledState: 'Enabled'
    sharedPrivateLinkResource: {
      privateLink: {
        id: appServiceWestEurope.id
      }
      groupId: 'sites'
      privateLinkLocation: 'westeurope'
      requestMessage: 'Front Door Private Link'
    }
  }
}

// Southeast Asia origin
resource originSEAsia 'Microsoft.Cdn/profiles/originGroups/origins@2023-05-01' = {
  parent: originGroup
  name: 'origin-seasia'
  properties: {
    hostName: 'app-seasia.azurewebsites.net'
    httpPort: 80
    httpsPort: 443
    originHostHeader: 'app-seasia.azurewebsites.net'
    priority: 1
    weight: 1000
    enabledState: 'Enabled'
    sharedPrivateLinkResource: {
      privateLink: {
        id: appServiceSEAsia.id
      }
      groupId: 'sites'
      privateLinkLocation: 'southeastasia'
      requestMessage: 'Front Door Private Link'
    }
  }
}

Step 3: Configure Routes with Caching

// Static content route with caching
resource staticRoute 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = {
  parent: frontDoorEndpoint
  name: 'static-route'
  properties: {
    customDomains: [
      {
        id: customDomain.id
      }
    ]
    originGroup: {
      id: originGroup.id
    }
    supportedProtocols: ['Https']
    patternsToMatch: [
      '/images/*'
      '/css/*'
      '/js/*'
      '/fonts/*'
    ]
    forwardingProtocol: 'HttpsOnly'
    linkToDefaultDomain: 'Enabled'
    httpsRedirect: 'Enabled'
    cacheConfiguration: {
      compressionSettings: {
        isCompressionEnabled: true
        contentTypesToCompress: [
          'text/html'
          'text/css'
          'application/javascript'
          'application/json'
          'image/svg+xml'
        ]
      }
      queryStringCachingBehavior: 'IgnoreQueryString'
      cacheBehavior: 'OverrideAlways'
      cacheDuration: 'P7D'  // 7 days for static assets
    }
  }
}

// API route without caching
resource apiRoute 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = {
  parent: frontDoorEndpoint
  name: 'api-route'
  properties: {
    customDomains: [
      {
        id: customDomain.id
      }
    ]
    originGroup: {
      id: originGroup.id
    }
    supportedProtocols: ['Https']
    patternsToMatch: ['/api/*']
    forwardingProtocol: 'HttpsOnly'
    linkToDefaultDomain: 'Enabled'
    httpsRedirect: 'Enabled'
    cacheConfiguration: {
      queryStringCachingBehavior: 'UseQueryString'
      cacheBehavior: 'HonorOrigin'  // Respect Cache-Control headers
    }
  }
}

// Default route
resource defaultRoute 'Microsoft.Cdn/profiles/afdEndpoints/routes@2023-05-01' = {
  parent: frontDoorEndpoint
  name: 'default-route'
  properties: {
    customDomains: [
      {
        id: customDomain.id
      }
    ]
    originGroup: {
      id: originGroup.id
    }
    supportedProtocols: ['Https']
    patternsToMatch: ['/*']
    forwardingProtocol: 'HttpsOnly'
    linkToDefaultDomain: 'Enabled'
    httpsRedirect: 'Enabled'
  }
}

Step 4: Configure WAF Policy

// WAF Policy with managed rules
resource wafPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPolicies@2022-05-01' = {
  name: 'waf-contoso-global'
  location: 'global'
  sku: {
    name: 'Premium_AzureFrontDoor'
  }
  properties: {
    policySettings: {
      mode: 'Prevention'  // Block attacks (use Detection for testing)
      requestBodyCheck: 'Enabled'
      maxRequestBodySizeInKb: 128
    }
    managedRules: {
      managedRuleSets: [
        {
          ruleSetType: 'Microsoft_DefaultRuleSet'
          ruleSetVersion: '2.1'
          ruleGroupOverrides: []
        }
        {
          ruleSetType: 'Microsoft_BotManagerRuleSet'
          ruleSetVersion: '1.0'
        }
      ]
    }
    customRules: {
      rules: [
        {
          name: 'BlockBadBots'
          priority: 1
          ruleType: 'MatchRule'
          action: 'Block'
          matchConditions: [
            {
              matchVariable: 'RequestHeaders'
              selector: 'User-Agent'
              operator: 'Contains'
              matchValue: ['bot', 'spider', 'crawler']
              transforms: ['Lowercase']
            }
          ]
        }
        {
          name: 'RateLimitByIP'
          priority: 2
          ruleType: 'RateLimitRule'
          rateLimitThreshold: 1000
          rateLimitDurationInMinutes: 1
          action: 'Block'
          matchConditions: [
            {
              matchVariable: 'RequestUri'
              operator: 'Contains'
              matchValue: ['/api/']
            }
          ]
        }
        {
          name: 'GeoBlockRule'
          priority: 3
          ruleType: 'MatchRule'
          action: 'Block'
          matchConditions: [
            {
              matchVariable: 'RemoteAddr'
              operator: 'GeoMatch'
              matchValue: ['CN', 'RU']  // Block specific countries
            }
          ]
        }
      ]
    }
  }
}

// Associate WAF with Front Door security policy
resource securityPolicy 'Microsoft.Cdn/profiles/securityPolicies@2023-05-01' = {
  parent: frontDoorProfile
  name: 'waf-security-policy'
  properties: {
    parameters: {
      type: 'WebApplicationFirewall'
      wafPolicy: {
        id: wafPolicy.id
      }
      associations: [
        {
          domains: [
            {
              id: customDomain.id
            }
          ]
          patternsToMatch: ['/*']
        }
      ]
    }
  }
}

Step 5: Geo-Routing for Compliance

// Rule set for geo-based routing (GDPR compliance)
resource ruleSet 'Microsoft.Cdn/profiles/ruleSets@2023-05-01' = {
  parent: frontDoorProfile
  name: 'geo-routing-rules'
}

resource euRoutingRule 'Microsoft.Cdn/profiles/ruleSets/rules@2023-05-01' = {
  parent: ruleSet
  name: 'route-eu-to-eu-origin'
  properties: {
    order: 1
    conditions: [
      {
        name: 'RemoteAddress'
        parameters: {
          typeName: 'DeliveryRuleRemoteAddressConditionParameters'
          operator: 'GeoMatch'
          matchValues: [
            'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI',
            'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU',
            'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE'
          ]
        }
      }
    ]
    actions: [
      {
        name: 'RouteConfigurationOverride'
        parameters: {
          typeName: 'DeliveryRuleRouteConfigurationOverrideActionParameters'
          originGroupOverride: {
            originGroup: {
              id: euOriginGroup.id  // EU-only origin group
            }
          }
        }
      }
    ]
  }
}

Step 6: Monitor and Alert

// Diagnostic settings
resource frontDoorDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'fd-diagnostics'
  scope: frontDoorProfile
  properties: {
    workspaceId: logAnalyticsWorkspace.id
    logs: [
      {
        category: 'FrontDoorAccessLog'
        enabled: true
      }
      {
        category: 'FrontDoorHealthProbeLog'
        enabled: true
      }
      {
        category: 'FrontDoorWebApplicationFirewallLog'
        enabled: true
      }
    ]
    metrics: [
      {
        category: 'AllMetrics'
        enabled: true
      }
    ]
  }
}

// Alert on origin health
resource originHealthAlert 'Microsoft.Insights/metricAlerts@2018-03-01' = {
  name: 'fd-origin-health-alert'
  location: 'global'
  properties: {
    description: 'Alert when origin health drops below threshold'
    severity: 1
    enabled: true
    scopes: [frontDoorProfile.id]
    evaluationFrequency: 'PT1M'
    windowSize: 'PT5M'
    criteria: {
      'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
      allOf: [
        {
          name: 'OriginHealthPercentage'
          metricName: 'OriginHealthPercentage'
          operator: 'LessThan'
          threshold: 80
          timeAggregation: 'Average'
        }
      ]
    }
    actions: [
      {
        actionGroupId: actionGroup.id
      }
    ]
  }
}
// KQL query for WAF blocked requests
AzureDiagnostics
| where Category == "FrontDoorWebApplicationFirewallLog"
| where action_s == "Block"
| summarize BlockedRequests = count() by
    ruleName_s,
    clientIp_s,
    requestUri_s
| order by BlockedRequests desc
| take 100

// KQL query for origin latency
AzureDiagnostics
| where Category == "FrontDoorAccessLog"
| summarize
    AvgLatency = avg(timeTaken_d),
    P95Latency = percentile(timeTaken_d, 95),
    P99Latency = percentile(timeTaken_d, 99)
by originName_s, bin(TimeGenerated, 5m)
| render timechart

Front Door vs Other Services

FeatureFront DoorTraffic ManagerApplication Gateway
Layer7 (HTTP)DNS7 (HTTP)
ScopeGlobalGlobalRegional
CDNBuilt-inNoNo
WAFYes (Premium)NoYes
Private LinkYes (Premium)NoYes
SSL OffloadYesNoYes
Latency-basedYesYesNo

Routing Methods

MethodUse Case
LatencyRoute to fastest origin
PriorityActive-passive failover
WeightedBlue-green deployments
Session AffinityStateful applications

Practice Question

Why use Azure Front Door Premium with Private Link to origins instead of public endpoints?