Cold Starts in Azure Functions

thumbnail for this post

This article describes Azure Functions running on Consumption Plan—the dynamically scaled and billed-per-execution compute service. Consumption Plan adds and removes instances dynamically. When a new instance handles its first request, the response time increases, which is called a cold start.

Learn more: Cold Starts in Serverless Functions.

When Does Cold Start Happen?

The very first cold start happens when the first request comes in after deployment.

After that request is processed, the instance stays alive for about 20 minutes to be reused for subsequent requests:

Probability of a cold start happening before minute X

As you can see, some cold starts happen earlier than 20 minutes, so this behavior seems less deterministic than it used to be in the past.

Read more: When Does Cold Start Happen on Azure Functions?

How Slow Are Cold Starts?

The following chart shows the typical range of cold starts in Azure Functions V2, broken down per language. The darker ranges are the most common 67% of durations, and lighter ranges include 95%.

Typical cold start durations per language

A typical cold start latency spans from 1 to 3 seconds. However, less lucky executions may take up to 10-15 seconds occasionally.

View detailed distributions: Cold Start Duration per Language.

Windows vs. Linux

Azure Functions can be deployed either on Windows or Linux environments, depending on the plan settings. Which operating system provides faster cold starts?

Comparison of cold start durations between two operating systems

Interestingly, there’s no clear winner. The median response time is lower on Windows, but Linux has tighter distribution.

Node is consistently slower than .NET or Python.

Is V2 Faster Than V1?

There are currently two generally available versions of Azure Functions runtime: V1 runs on top of .NET Framework 4.x, while V2 runs on .NET Core 2.x.

Even though .NET Core is supposed to be faster and more lightweight, the cold starts of Functions V2 are comparable to V1:

Comparison of cold start durations across runtime versions

The results are mixed: V2 .NET is faster than V1 .NET, while V2 JavaScript functions are slower than V1.

Does Package Size Matter?

The above charts show the statistics for tiny “Hello World”-style functions. Adding dependencies and thus increasing the deployed package size will further increase the cold start durations.

The following chart compares three JavaScript functions with the various number of referenced NPM packages:

Comparison of cold start durations per deployment size (zipped)

Indeed, the functions with many dependencies can be several times slower to start.

Does Deployment Method Matter?

There are multiple ways to deploy Azure Functions. The charts below compare three of them:

  • No Zip—traditional AppService-style deployment based on Kudu (--nozip option in func CLI)
  • Local Zip—uploading a zip package to the local file system of the Function App and setting RUN_FROM_PACKAGE=1 in application settings
  • External Zip—uploading a zip package to blob storage and setting RUN_FROM_PACKAGE=<blob sas token> in application settings

Cold start durations per deployment method for C# functions

Cold start durations per deployment method for JavaScript functions

It turns out that No Zip is faster than Local Zip which is faster than External Zip, but the differences are not dramatic.

Visit the Github Issue to comment on this page