Hi Antimatter,
Thank you for sharing the code snippet. Looking at your queue trigger definition, there are two critical areas that frequently cause silent failures or trigger-sync issues on the Flex Consumption plan: the connection reference and the asynchronous implementation.
1. The AzureWebJobsStorage Connection in Flex Consumption: In the traditional Consumption plan, AzureWebJobsStorage is implicitly handled as a default connection string by the host. However, the Flex Consumption plan is heavily optimized for secure, identity-based connections and handles networking/scaling differently.
Since you have explicitly set connection="AzureWebJobsStorage", you must ensure this exact setting exists and is formatted correctly in your Function App's Environment Variables.
- If you are using an Azure Storage connection string, ensure there is an app setting named
AzureWebJobsStorage containing the full connection string.
- If you are using Managed Identity (the recommended approach for Flex Consumption), you need an environment variable named
AzureWebJobsStorage__queueServiceUri pointing to your storage account (e.g., https://<storage_account>.queue.core.windows.net).
- Your Function App's managed identity must also be assigned the Storage Queue Data Message Processor role on that storage account.
If this connection is missing, misconfigured, or lacks IAM permissions, the scale controller cannot access the queue to read metadata, resulting in the triggers: null behavior and the function never firing.
2. Native Async Support (The asyncio.run Anti-Pattern): You are defining a synchronous handler (def my_push_worker) and manually invoking an event loop using asyncio.run(). This is an anti-pattern in Azure Functions. The Python worker manages its own thread pool and event loop. Manually creating a new event loop inside a synchronous thread can lead to thread-pool exhaustion, worker crashes, or deadlocks, which disrupts the host's ability to process events.
The Azure Functions Python worker natively supports asynchronous execution. You should define your trigger directly as a coroutine using async def.
From official Microsoft documentation:
"When you write a function in Python, you can write it as an asynchronous coroutine... The Azure Functions Python worker natively supports asynchronous execution. Asynchronous Python functions can help to improve the performance of your application by allowing it to process other tasks while waiting for I/O operations to complete."
Reference: Improve throughput performance of Python apps in Azure Functions
Here is how your code should be refactored:
import azure.functions as func
import logging
app = func.FunctionApp()
@app.queue_trigger(
arg_name="msg",
queue_name="my-push-jobs",
connection="AzureWebJobsStorage"
)
async def my_push_worker(msg: func.QueueMessage) -> None:
logging.info('Processing message: %s', msg.get_body().decode('utf-8'))
# Natively await your asynchronous worker instead of using asyncio.run()
await _my_push_worker_async(msg)
Please let me know if it works and share your findings.
Note: This response is generated with the help of AI systems.