Introduction
Azure Functions on the Consumption plan automatically scales out by adding instances when trigger events increase. When the scale controller fails to respond, functions process events serially on a single instance, causing massive backlogs. This is critical for event-driven architectures processing queues, blobs, or Event Hubs.
Symptoms
- Queue messages accumulate but only one Function App instance processes them
- Azure Monitor shows single instance running despite high trigger count
FunctionExecutionCountmetric is flat while queue depth grows- Scale controller logs show no new instance allocation events
Common Causes
- Storage account used for triggers is in a different region than the Function App
- App Service plan (not Consumption plan) selected - manual scaling required
- Host.json
maxPollingIntervalset too high, delaying trigger detection - Scale controller throttled due to too many Function Apps in the subscription
- Function App using premium plan with pre-warmed instances exhausted
Step-by-Step Fix
- 1.Check the hosting plan type:
- 2.```bash
- 3.az functionapp show --name my-function --resource-group my-rg \
- 4.--query '{Plan:serverFarmId,Sku:sku}'
- 5.
` - 6.Consumption plan shows
sku: Y1. If it showsB1,S1, etc., you're on App Service plan and need to manually scale. - 7.Check storage account region matches Function App region:
- 8.```bash
- 9.az functionapp config appsettings list --name my-function --resource-group my-rg \
- 10.--query "[?name=='AzureWebJobsStorage'].value"
- 11.
` - 12.The storage connection string should point to a storage account in the same region.
- 13.Optimize host.json trigger settings:
- 14.```json
- 15.{
- 16."version": "2.0",
- 17."extensions": {
- 18."queues": {
- 19."maxPollingInterval": "00:00:02",
- 20."batchSize": 16,
- 21."newBatchThreshold": 8,
- 22."maxDequeueCount": 5
- 23.}
- 24.}
- 25.}
- 26.
` - 27.Lower
maxPollingIntervalfrom default 1 minute to 2 seconds for faster response. - 28.Check scale controller status:
- 29.```bash
- 30.az monitor metrics list \
- 31.--resource my-function \
- 32.--resource-group my-rg \
- 33.--metric "FunctionExecutionUnits" \
- 34.--interval PT1M \
- 35.--query 'value[0].timeseries[0].data'
- 36.
` - 37.Force scale-out by increasing concurrency:
- 38.For HTTP-triggered functions, increase
maxConcurrentRequestsin host.json: - 39.```json
- 40.{
- 41."extensions": {
- 42."http": {
- 43."maxConcurrentRequests": 200,
- 44."maxOutstandingRequests": 300
- 45.}
- 46.}
- 47.}
- 48.
`
Prevention
- Use Consumption plan for automatic scaling
- Keep trigger storage account in the same region as the Function App
- Monitor
FunctionExecutionUnitsand queue depth with alerts - Set appropriate batchSize and polling interval for your workload
- Consider Premium plan for predictable scaling with pre-warmed instances