Domain 3 β€” Module 5 of 6 83%
21 of 27 overall
Domain 3: Connect to and consume Azure services Free ⏱ ~12 min read

Function Apps: Configuration + Deployment

Hosting plans, app settings, deployment slots, identity, deployment with zip-deploy and CI/CD, and the Container-Apps-hosted Functions option for AI workloads with custom dependencies.

Hosting plans β€” the four flavours

Simple explanation

Functions can run on four different hosting plans, and the right one matters.

  • Consumption β€” classic serverless. Pay per execution. Scale to zero. Cold starts. 5-10 minute timeout.
  • Premium β€” pre-warmed instances, VNet integration, longer timeouts (30 min default, unbounded max), no cold starts.
  • Flex Consumption β€” newer; per-instance memory choice, VNet integration, scale-to-zero.
  • Container Apps β€” Functions running on Azure Container Apps. KEDA scaling, GPU support, custom dependencies, the AI-friendly choice.

The exam tests when to pick which. Hint: Consumption fits hobby/light workloads; Premium fits steady production; Container Apps fits AI workloads with model dependencies or GPU needs.

Four hosting plans. For AI back-ends, Premium or Container Apps usually win.
FeatureConsumptionPremiumFlex ConsumptionContainer Apps
Pricing modelPer execution + GB-s of memoryPre-paid + per-executionPer-second by instance memoryPay per active container
Scale to zeroYes (cold start)No (always-warm)YesYes
Max timeout5 min default, 10 min max (Windows only β€” Linux Consumption is retired)30 min default, unbounded max30 min default, unbounded maxUnbounded (set per Container App)
VNet integrationNoYesYesYes (Container Apps environment)
Custom containerLinux only, limitedYesYesNative β€” bring any container
Best forLight reactive code, dev/testSteady production with VNet needsModern serverless with VNet + scale-to-zeroAI workloads with model deps, GPU, large images

Functions on Container Apps β€” the AI-friendly path

Functions on Container Apps brings the Azure Functions programming model (triggers, bindings) onto the Azure Container Apps platform β€” KEDA scaling, GPU support, multi-container, scale-to-zero β€” without losing the binding productivity.

# Create a function app on Container Apps
az functionapp create \
  --name roo-embed \
  --resource-group roo-prod \
  --environment roo-prod-cae \
  --image roo.azurecr.io/roo-embed:v1.0.0 \
  --workload-profile-name Consumption \
  --runtime python --runtime-version 3.12 \
  --kind functionapp \
  --storage-account roostore

This is the path for AI Functions that need:

  • A custom container with model dependencies (transformers, torch, ONNX runtime)
  • GPU profiles
  • Larger images than the default Functions package size
  • Co-existence with non-Function container apps in the same environment

App settings β€” environment variables for your Functions

App settings are environment variables for the function host. Three patterns:

PatternUse
Direct valueNon-secret config β€” LogLevel=Information
Key Vault referenceSecrets β€” OpenAIKey=@Microsoft.KeyVault(SecretUri=https://roo-kv.vault.azure.net/secrets/OpenAIKey)
Managed identity (__fullyQualifiedNamespace)Service connections β€” Service Bus, Event Hubs, Cosmos with passwordless auth
az functionapp config appsettings set \
  --name roo-fn -g roo-prod \
  --settings \
    "AzureWebJobsStorage__accountName=roostore" \
    "ServiceBusConnection__fullyQualifiedNamespace=roo-sb.servicebus.windows.net" \
    "OpenAIKey=@Microsoft.KeyVault(SecretUri=https://roo-kv.vault.azure.net/secrets/OpenAIKey)"

Two app settings the runtime relies on:

SettingWhat it does
AzureWebJobsStorageStorage account for the host’s metadata, leases, large message queueing
FUNCTIONS_EXTENSION_VERSIONFunctions runtime version (~4 for current)

AzureWebJobsStorage should always use __accountName with managed identity in production β€” the older approach of putting a connection string here is a security smell.

Identity β€” how Functions authenticates to other Azure services

# Enable system-assigned managed identity on the function app
az functionapp identity assign --name roo-fn --resource-group roo-prod

# Grant it Service Bus Data Receiver
az role assignment create \
  --assignee $(az functionapp identity show -n roo-fn -g roo-prod --query principalId -o tsv) \
  --role "Azure Service Bus Data Receiver" \
  --scope $(az servicebus namespace show -n roo-sb -g roo-prod --query id -o tsv)

Combined with the __fullyQualifiedNamespace app-settings convention, every Service Bus trigger and binding now authenticates as the function’s identity β€” no secrets in app settings, full Microsoft Entra audit on every connection.

Deployment options

MethodUse
Zip DeployQuick start: func azure functionapp publish or az functionapp deployment source config-zip
Container imagePremium / Container Apps: build, push to ACR, set image
GitHub ActionsProduction CI/CD with build, test, deploy steps and slot swap
Azure DevOps PipelinesSame as GHA, in the Microsoft tooling stack
# Minimal GitHub Actions to deploy a Python function app
name: deploy-function
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install -r requirements.txt --target .python_packages/lib/site-packages
      - uses: Azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      - uses: Azure/functions-action@v1
        with:
          app-name: roo-fn
          slot-name: staging       # deploy to staging slot
          package: .

Deployment slots β€” same idea as App Service

Premium and Container Apps Function Apps support deployment slots. Same pattern as App Service:

  1. Deploy to staging slot
  2. Smoke test against the staging URL
  3. Swap β†’ production now points to the new code, staging holds the old
  4. Roll back by swapping again

Slot-specific app settings (those marked β€œSlot setting”) stay with the slot during a swap β€” useful when staging targets a sandbox OpenAI endpoint and production targets the real one.

Real-world example: Lin's three-stage rollout

Lin deploys a client-facing Function that calls Azure OpenAI. Pipeline:

  1. Push to main β†’ GitHub Actions deploys to the staging slot
  2. Synthetic test (a Function-Postman collection) hits 5 representative routes
  3. If green, GHA calls az functionapp deployment slot swap to swap staging β†’ production
  4. Watch Application Insights error rate for 10 minutes
  5. If error rate spikes, GHA swaps back automatically

Three slot-specific app settings: API base URL, model deployment name, log sampling rate. They stay with their slot, so production never accidentally talks to a sandbox endpoint.

Cold start mitigation

Consumption plan cold starts are the most common AI-200 question gotcha. Three options to mitigate:

OptionTrade-off
Premium plan with always-ready instancesBest β€” eliminates cold start at the cost of always-on compute
Health-check pings (warm-up)Free but unreliable β€” Azure may evict during quiet periods
Move to Container Apps with min replicas = 1Eliminates cold start; pays for the minimum replica

For Python/Node functions with light dependencies, cold starts are seconds. For Functions with heavy ML libraries (torch, transformers), cold starts can be tens of seconds β€” that’s when Premium or Container Apps becomes the right choice.

Key terms

Question

What's the cold-start trade-off in the Consumption plan?

Click or press Enter to reveal answer

Answer

Consumption scales to zero (no cost when idle) but the first request after an idle period waits for an instance to start. Cold start is seconds for light functions and tens of seconds for AI Functions with heavy ML deps. Premium and Container Apps with min replicas eliminate cold start.

Click to flip back

Question

What is `AzureWebJobsStorage`, and why use `__accountName`?

Click or press Enter to reveal answer

Answer

The Storage account the Functions host uses for its metadata, leases, large message queueing. Using `__accountName=<name>` (instead of a connection string) tells the host to authenticate via the function's managed identity β€” passwordless and auditable.

Click to flip back

Question

When should you choose Functions on Container Apps over Premium plan?

Click or press Enter to reveal answer

Answer

When the workload needs custom container images (heavy ML deps), GPU support, larger images than Functions package limits, or you want it to coexist with other Container Apps in the same environment with a single networking + identity story. Container Apps is the AI-friendly option.

Click to flip back

Question

What's the safe way to deploy a new version of a Function App with rollback?

Click or press Enter to reveal answer

Answer

Deployment slots (Premium / Container Apps). Deploy to staging, smoke test, swap into production. If the new version misbehaves, swap back immediately β€” the previous version is still in the staging slot. Slot-specific settings (API endpoints, model names) follow their slot.

Click to flip back

Question

What's `FUNCTIONS_EXTENSION_VERSION`?

Click or press Enter to reveal answer

Answer

The Functions runtime version. `~4` for the current GA runtime (v4). Pin this in app settings β€” accidentally upgrading to a future major version can break bindings or programming models.

Click to flip back

Knowledge check

Knowledge Check

Mira's embed function uses transformers and torch. The container image is 4.2 GB. Cold start on Consumption plan takes 45 seconds. She doesn't want to abandon scale-to-zero. What's the best fit?

Knowledge Check

Theo wants the Function App's managed identity to read secrets from Key Vault. The app settings already include `OpenAIKey=@Microsoft.KeyVault(SecretUri=https://...)`. What else must be true?

Knowledge Check

Lin's pipeline pushes a new function image. He wants production to switch to the new version atomically AND keep an instant rollback path. What feature should he use?