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
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.
| Feature | Consumption | Premium | Flex Consumption | Container Apps |
|---|---|---|---|---|
| Pricing model | Per execution + GB-s of memory | Pre-paid + per-execution | Per-second by instance memory | Pay per active container |
| Scale to zero | Yes (cold start) | No (always-warm) | Yes | Yes |
| Max timeout | 5 min default, 10 min max (Windows only β Linux Consumption is retired) | 30 min default, unbounded max | 30 min default, unbounded max | Unbounded (set per Container App) |
| VNet integration | No | Yes | Yes | Yes (Container Apps environment) |
| Custom container | Linux only, limited | Yes | Yes | Native β bring any container |
| Best for | Light reactive code, dev/test | Steady production with VNet needs | Modern serverless with VNet + scale-to-zero | AI 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:
| Pattern | Use |
|---|---|
| Direct value | Non-secret config β LogLevel=Information |
| Key Vault reference | Secrets β 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:
| Setting | What it does |
|---|---|
AzureWebJobsStorage | Storage account for the hostβs metadata, leases, large message queueing |
FUNCTIONS_EXTENSION_VERSION | Functions 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
| Method | Use |
|---|---|
| Zip Deploy | Quick start: func azure functionapp publish or az functionapp deployment source config-zip |
| Container image | Premium / Container Apps: build, push to ACR, set image |
| GitHub Actions | Production CI/CD with build, test, deploy steps and slot swap |
| Azure DevOps Pipelines | Same 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:
- Deploy to
stagingslot - Smoke test against the staging URL
- Swap β production now points to the new code, staging holds the old
- 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:
- Push to
mainβ GitHub Actions deploys to the staging slot - Synthetic test (a Function-Postman collection) hits 5 representative routes
- If green, GHA calls
az functionapp deployment slot swapto swap staging β production - Watch Application Insights error rate for 10 minutes
- 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:
| Option | Trade-off |
|---|---|
| Premium plan with always-ready instances | Best β 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 = 1 | Eliminates 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
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?
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?
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?