Some Real Performance Numbers from Some Real Azure Functions

I’ve been using Azure Functions in various production systems since late 2016. If you wonder how real apps perform using a consumption plan with auto-scaling (which means pay as you go based on usage), I have some data for you!

First up
is the most commonly executed function in my busiest production installation of Azure Functions for SharePoint. The EventDispatch function receives event notifications from various SharePoint Online tenants for a few different apps. When something of interest happens in a SharePoint site, Microsoft sends the EventDispatch function an HTTP POST request. EventDispatch process this message and drops the result into the Service Bus queue for whatever app that created the event receiver subscription.

Over the last 8 days or so this function was triggered around 40,000 times a day at an error rate of about 4 per day.

SharePoint waits for a response from the event receiver for some events and a user experiences this as a delay when this kind of event fires. Therefore, EventDispatch needs to run quickly. One thing people new to Azure Functions sometimes notice is with consumption-based function apps is that functions triggered by web requests are slow during requests that cause Azure to load the function. Fortunately, the traffic to this function is steady. This means that the startup operation happens in a tiny percent of requests and performance is excellent.

The following charts show what normal traffic looks like. Scouts honor! I opened the Application Insights for this app and took a screenshot of the point in time sometimes there is much more traffic and other times there is much less.

This function app and its associated storage account costs me less around $10 a month. The storage account is around 60% of the total cost and there is room for some optimization.

Next up is application specific functionality hosted in a different function app in a different Azure tenant. This particular function app is a bit of a grab bag in terms of individual functions and has a lot of room for improvement in a couple of ways, the least of which is the mingling of a long-running process that introduces a few other issues which are a subject for another day and another post.

The long running process fires periodically based on scheduled message delivery and that schedule causes all of the messages to begin delivery at the same time subject. On top of that, the way I wrote it is dumb and the job takes much longer to execute than it should. So, during the periods when it runs it forces the function app to scale and load on a lot of servers. The numbers are pretty grim.

That high server count represents instances of the app, and it is wasted consumption that costs money. One thing I have noticed is that instances are slow to unwind.

Nevertheless, this badly written function inside this grab-bag app still only costs around $45 a month. I haven’t fixed it because the cost is too low to justify fixing it.