Symptom
HTTP functions take several seconds on the first call after idle; queue backlogs build up before scale-out kicks in; or a Premium plan runs all month for a function used twice a day.
1. Measure cold starts
In Application Insights:
requests
| where timestamp > ago(7d) and cloud_RoleName == "func-orders"
| summarize p50 = percentile(duration, 50), p95 = percentile(duration, 95), p99 = percentile(duration, 99) by bin(timestamp, 1h)
| render timechart
traces
| where timestamp > ago(7d) and message has "Host started"
| summarize starts = count() by bin(timestamp, 1h), cloud_RoleInstance
Spikes in p99 aligned with host starts are cold starts.
2. Make start-up cheaper (any plan)
| Cause | Fix |
|---|---|
| Large deployment package | Remove unused dependencies; run from package |
| Heavy work in static constructors / module import | Lazy-load clients; create SDK clients once and reuse |
| Many functions in one app with large dependency trees | Split rarely used heavy functions into another app |
| Python imports of big libraries at module level | Import inside the function or trim the library |
| Key Vault references and config fetched slowly | Cache; check network path to Key Vault |
| .NET in-process model | Move to isolated worker (in-process support ends; check the date) |
3. Choose the plan
| Need | Plan |
|---|---|
| Low, spiky volume; occasional cold start OK; no VNet | Consumption |
| Pay-per-use with VNet integration, faster scale, optional always-ready instances | Flex Consumption |
| No cold start at all, long-running functions, larger instances | Premium (Elastic Premium) with pre-warmed instances |
| Spare App Service capacity, predictable load | Dedicated (App Service plan) with Always On |
Linux Consumption has an announced retirement path, and Flex Consumption is the suggested direction for new serverless apps. Check the current timelines and Flex feature/region support before moving.
4. Flex Consumption settings
az functionapp create -g rg-func -n func-orders --storage-account stfuncorders \
--flexconsumption-location westeurope --runtime dotnet-isolated --runtime-version 8.0 \
--instance-memory 2048
az functionapp scale config always-ready set -g rg-func -n func-orders --settings http=1
az functionapp scale config set -g rg-func -n func-orders --maximum-instance-count 40 \
--trigger-type http --trigger-settings perInstanceConcurrency=16
- Always-ready instances remove cold starts for the chosen trigger groups, at a baseline cost.
- Instance memory affects CPU share and price. Test 2,048 vs 4,096 MB for CPU-heavy work.
- Per-instance concurrency for HTTP: higher packs more requests per instance (cheaper) until latency suffers.
- Max instance count protects downstream systems (databases) from being overwhelmed.
5. Premium plan settings
az functionapp plan update -g rg-func -n plan-func-prem --min-instances 1 --max-burst 20
az resource update -g rg-func -n func-orders/config/web --set properties.preWarmedInstanceCount=1 \
--resource-type Microsoft.Web/sites
Minimum instances are always billed. Size them for the baseline, not the peak.
6. Tune triggers for throughput
| Trigger | Setting (host.json) |
|---|---|
| Storage queue | batchSize, newBatchThreshold |
| Service Bus | maxConcurrentCalls, prefetchCount, sessions |
| Event Hubs | maxEventBatchSize, partitions = max parallel instances |
| HTTP | Per-instance concurrency (Flex), dynamic concurrency ("concurrency": {"dynamicConcurrencyEnabled": true}) |
7. Cost check
Compare a month of executions × duration × memory (Consumption/Flex) against Premium minimum instances. Low and spiky volume favours per-use plans, while high and steady volume can favour Premium or Dedicated.
Tip
If only one HTTP endpoint is latency-sensitive, give it its own small Function app with always-ready instances, and leave the background functions on pure pay-per-use.
Checklist
- Cold starts measured (p99 vs host starts)
- Start-up work trimmed in code and package
- Plan chosen by latency, VNet and runtime needs
- Always-ready / pre-warmed sized to baseline
- Trigger concurrency and max instances tuned
- Monthly cost compared across plans