Azure Functions developer guide
In Azure Functions, specific functions share a few core technical concepts and components, regardless of the language or binding you use. Before you jump into learning details specific to a given language or binding, be sure to read through this overview that applies to all of them.
This article assumes that you've already read the Azure Functions overview.
Function code
A function is the primary concept in Azure Functions. A function contains two important pieces - your code, which can be written in a variety of languages, and some config, the function.json file. For compiled languages, this config file is generated automatically from annotations in your code. For scripting languages, you must provide the config file yourself.
The function.json file defines the function's trigger, bindings, and other configuration settings. Every function has one and only one trigger. The runtime uses this config file to determine the events to monitor and how to pass data into and return data from a function execution. The following is an example function.json file.
{
"disabled":false,
"bindings":[
// ... bindings here
{
"type": "bindingType",
"direction": "in",
"name": "myParamName",
// ... more depending on binding
}
]
}
For more information, see Azure Functions triggers and bindings concepts.
The bindings
property is where you configure both triggers and bindings. Each binding shares a few common settings and some settings, which are specific to a particular type of binding. Every binding requires the following settings:
Property | Values | Type | Comments |
---|---|---|---|
type | Name of binding. For example, queueTrigger . |
string | |
direction | in , out |
string | Indicates whether the binding is for receiving data into the function or sending data from the function. |
name | Function identifier. For example, myQueue . |
string | The name that is used for the bound data in the function. For C#, this is an argument name; for JavaScript, it's the key in a key/value list. |
Function app
A function app provides an execution context in Azure in which your functions run. As such, it is the unit of deployment and management for your functions. A function app is composed of one or more individual functions that are managed, deployed, and scaled together. All of the functions in a function app share the same pricing plan, deployment method, and runtime version. Think of a function app as a way to organize and collectively manage your functions. To learn more, see How to manage a function app.
Note
All functions in a function app must be authored in the same language. In previous versions of the Azure Functions runtime, this wasn't required.
Folder structure
The code for all the functions in a specific function app is located in a root project folder that contains a host configuration file. The host.json file contains runtime-specific configurations and is in the root folder of the function app. A bin folder contains packages and other library files that the function app requires. Specific folder structures required by the function app depend on language:
In version 2.x and higher of the Functions runtime, all functions in the function app must share the same language stack.
The above is the default (and recommended) folder structure for a Function app. If you wish to change the file location of a function's code, modify the scriptFile
section of the function.json file. We also recommend using package deployment to deploy your project to your function app in Azure. You can also use existing tools like continuous integration and deployment and Azure DevOps.
Note
If deploying a package manually, make sure to deploy your host.json file and function folders directly to the wwwroot
folder. Do not include the wwwroot
folder in your deployments. Otherwise, you end up with wwwroot\wwwroot
folders.
Use local tools and publishing
Function apps can be authored and published using a variety of tools, including Visual Studio, Visual Studio Code, IntelliJ, Eclipse, and the Azure Functions Core Tools. For more information, see Code and test Azure Functions locally.
How to edit functions in the Azure portal
The Functions editor built into the Azure portal lets you update your code and your function.json file directly inline. This is recommended only for small changes or proofs of concept - best practice is to use a local development tool like VS Code.
Parallel execution
When multiple triggering events occur faster than a single-threaded function runtime can process them, the runtime may invoke the function multiple times in parallel. If a function app is using the Consumption hosting plan, the function app could scale out automatically. Each instance of the function app, whether the app runs on the Consumption hosting plan or a regular App Service hosting plan, might process concurrent function invocations in parallel using multiple threads. The maximum number of concurrent function invocations in each function app instance varies based on the type of trigger being used as well as the resources used by other functions within the function app.
Functions runtime versioning
You can configure the version of the Functions runtime using the FUNCTIONS_EXTENSION_VERSION
app setting. For example, the value "~3" indicates that your function app will use 3.x as its major version. Function apps are upgraded to each new minor version as they are released. For more information, including how to view the exact version of your function app, see How to target Azure Functions runtime versions.
Repositories
The code for Azure Functions is open source and stored in GitHub repositories:
- Azure Functions
- Azure Functions host
- Azure Functions portal
- Azure Functions templates
- Azure WebJobs SDK
- Azure WebJobs SDK Extensions
Bindings
Here is a table of all supported bindings.
This table shows the bindings that are supported in the major versions of the Azure Functions runtime:
Type | 1.x | 2.x and higher1 | Trigger | Input | Output |
---|---|---|---|---|---|
Blob storage | ✔ | ✔ | ✔ | ✔ | ✔ |
Azure Cosmos DB | ✔ | ✔ | ✔ | ✔ | ✔ |
Azure SQL | ✔ | ✔ | ✔ | ✔ | |
Dapr3 | ✔ | ✔ | ✔ | ✔ | |
Event Grid | ✔ | ✔ | ✔ | ✔ | |
Event Hubs | ✔ | ✔ | ✔ | ✔ | |
HTTP & webhooks | ✔ | ✔ | ✔ | ✔ | |
IoT Hub | ✔ | ✔ | ✔ | ||
Kafka2 | ✔ | ✔ | ✔ | ||
Mobile Apps | ✔ | ✔ | ✔ | ||
Notification Hubs | ✔ | ✔ | |||
Queue storage | ✔ | ✔ | ✔ | ✔ | |
RabbitMQ2 | ✔ | ✔ | ✔ | ||
SendGrid | ✔ | ✔ | ✔ | ||
Service Bus | ✔ | ✔ | ✔ | ✔ | |
SignalR | ✔ | ✔ | ✔ | ✔ | |
Table storage | ✔ | ✔ | ✔ | ✔ | |
Timer | ✔ | ✔ | ✔ | ||
Twilio | ✔ | ✔ | ✔ |
1 Starting with the version 2.x runtime, all bindings except HTTP and Timer must be registered. See Register binding extensions.
2 Triggers aren't supported in the Consumption plan. Requires runtime-driven triggers.
3 Supported only in Kubernetes, IoT Edge, and other self-hosted modes only.
Having issues with errors coming from the bindings? Review the Azure Functions Binding Error Codes documentation.
Connections
Your function project references connection information by name from its configuration provider. It does not directly accept the connection details, allowing them to be changed across environments. For example, a trigger definition might include a connection
property. This might refer to a connection string, but you cannot set the connection string directly in a function.json
. Instead, you would set connection
to the name of an environment variable that contains the connection string.
The default configuration provider uses environment variables. These might be set by Application Settings when running in the Azure Functions service, or from the local settings file when developing locally.
Connection values
When the connection name resolves to a single exact value, the runtime identifies the value as a connection string, which typically includes a secret. The details of a connection string are defined by the service to which you wish to connect.
However, a connection name can also refer to a collection of multiple configuration items, useful for configuring identity-based connections. Environment variables can be treated as a collection by using a shared prefix that ends in double underscores __
. The group can then be referenced by setting the connection name to this prefix.
For example, the connection
property for an Azure Blob trigger definition might be "Storage1". As long as there is no single string value configured by an environment variable named "Storage1", an environment variable named Storage1__blobServiceUri
could be used to inform the blobServiceUri
property of the connection. The connection properties are different for each service. Refer to the documentation for the component that uses the connection.
Note
When using Azure App Configuration or Key Vault to provide settings for Managed Identity connections, setting names should use a valid key separator such as :
or /
in place of the __
to ensure names are resolved correctly.
For example, Storage1:blobServiceUri
.
Configure an identity-based connection
Some connections in Azure Functions can be configured to use an identity instead of a secret. Support depends on the extension using the connection. In some cases, a connection string may still be required in Functions even though the service to which you are connecting supports identity-based connections. For a tutorial on configuring your function apps with managed identities, see the creating a function app with identity-based connections tutorial.
The following components support identity-based connections:
When hosted in the Azure Functions service, identity-based connections use a managed identity. The system-assigned identity is used by default, although a user-assigned identity can be specified with the credential
and clientID
properties. Note that configuring a user-assigned identity with a resource ID is not supported. When run in other contexts, such as local development, your developer identity is used instead, although this can be customized. See Local development with identity-based connections.
Grant permission to the identity
Whatever identity is being used must have permissions to perform the intended actions. For most Azure services, this means you need to assign a role in Azure RBAC, using either built-in or custom roles which provide those permissions.
Important
Some permissions might be exposed by the target service that are not necessary for all contexts. Where possible, adhere to the principle of least privilege, granting the identity only required privileges. For example, if the app only needs to be able to read from a data source, use a role that only has permission to read. It would be inappropriate to assign a role that also allows writing to that service, as this would be excessive permission for a read operation. Similarly, you would want to ensure the role assignment is scoped only over the resources that need to be read.
Choose a tab below to learn about permissions for each component:
- Azure Blobs extension
- Azure Queues extension
- Azure Tables extension
- Event Hubs extension
- Service Bus extension
- Azure Cosmos DB extension
- Azure SignalR extension
- Durable Functions storage provider
- Functions host storage
You need to create a role assignment that provides access to your blob container at runtime. Management roles like Owner aren't sufficient. The following table shows built-in roles that are recommended when using the Blob Storage extension in normal operation. Your application may require further permissions based on the code you write.
Binding type | Example built-in roles |
---|---|
Trigger | Storage Blob Data Owner and Storage Queue Data Contributor1 Extra permissions must also be granted to the AzureWebJobsStorage connection.2 |
Input binding | Storage Blob Data Reader |
Output binding | Storage Blob Data Owner |
1 The blob trigger handles failure across multiple retries by writing poison blobs to a queue on the storage account specified by the connection.
2 The AzureWebJobsStorage connection is used internally for blobs and queues that enable the trigger. If it's configured to use an identity-based connection, it needs extra permissions beyond the default requirement. The required permissions are covered by the Storage Blob Data Owner, Storage Queue Data Contributor, and Storage Account Contributor roles. To learn more, see Connecting to host storage with an identity.
Common properties for identity-based connections
An identity-based connection for an Azure service accepts the following common properties, where <CONNECTION_NAME_PREFIX>
is the value of your connection
property in the trigger or binding definition:
Property | Environment variable template | Description |
---|---|---|
Token Credential | <CONNECTION_NAME_PREFIX>__credential |
Defines how a token should be obtained for the connection. This setting is recommended only when specifying a user-assigned identity, when it should be set to "managedidentity". This value is only valid when hosted in the Azure Functions service. |
Client ID | <CONNECTION_NAME_PREFIX>__clientId |
When credential is set to "managedidentity", this property specifies the user-assigned identity to be used when obtaining a token. The property accepts a client ID corresponding to a user-assigned identity assigned to the application. If not specified, the system-assigned identity is used. This property is used differently in local development scenarios, when credential should not be set. |
Additional options may be supported for a given connection type. Refer to the documentation for the component making the connection.
Local development with identity-based connections
Note
Local development with identity-based connections requires updated versions of the Azure Functions Core Tools. You can check your currently installed version by running func -v
. For Functions v3, use version 3.0.3904
or later. For Functions v4, use version 4.0.3904
or later.
When you are running your function project locally, the above configuration tells the runtime to use your local developer identity. The connection attempts to get a token from the following locations, in order:
- A local cache shared between Microsoft applications
- The current user context in Visual Studio
- The current user context in Visual Studio Code
- The current user context in the Azure CLI
If none of these options are successful, an error will occur.
Your identity may already have some role assignments against Azure resources used for development, but those roles may not provide the necessary data access. Management roles like Owner are not sufficient. Double-check what permissions are required for connections for each component, and make sure that you have them assigned to yourself.
In some cases, you may wish to specify use of a different identity. You can add configuration properties for the connection that point to the alternate identity based on a client ID and client Secret for an Azure Active Directory service principal. This configuration option is not supported when hosted in the Azure Functions service. To use an ID and secret on your local machine, define the connection with the following additional properties:
Property | Environment variable template | Description |
---|---|---|
Tenant ID | <CONNECTION_NAME_PREFIX>__tenantId |
The Azure Active Directory tenant (directory) ID. |
Client ID | <CONNECTION_NAME_PREFIX>__clientId |
The client (application) ID of an app registration in the tenant. |
Client secret | <CONNECTION_NAME_PREFIX>__clientSecret |
A client secret that was generated for the app registration. |
Here is an example of local.settings.json
properties required for identity-based connection to Azure Blobs:
{
"IsEncrypted": false,
"Values": {
"<CONNECTION_NAME_PREFIX>__blobServiceUri": "<blobServiceUri>",
"<CONNECTION_NAME_PREFIX>__queueServiceUri": "<queueServiceUri>",
"<CONNECTION_NAME_PREFIX>__tenantId": "<tenantId>",
"<CONNECTION_NAME_PREFIX>__clientId": "<clientId>",
"<CONNECTION_NAME_PREFIX>__clientSecret": "<clientSecret>"
}
}
Connecting to host storage with an identity
The Azure Functions host uses the "AzureWebJobsStorage" connection for core behaviors such as coordinating singleton execution of timer triggers and default app key storage. This can be configured to leverage an identity as well.
Caution
Other components in Functions rely on "AzureWebJobsStorage" for default behaviors. You should not move it to an identity-based connection if you are using older versions of extensions that do not support this type of connection, including triggers and bindings for Azure Blobs, Event Hubs, and Durable Functions. Similarly, AzureWebJobsStorage
is used for deployment artifacts when using server-side build in Linux Consumption, and if you enable this, you will need to deploy via an external deployment package.
In addition, some apps reuse "AzureWebJobsStorage" for other storage connections in their triggers, bindings, and/or function code. Make sure that all uses of "AzureWebJobsStorage" are able to use the identity-based connection format before changing this connection from a connection string.
To use an identity-based connection for "AzureWebJobsStorage", configure the following app settings:
Setting | Description | Example value |
---|---|---|
AzureWebJobsStorage__blobServiceUri |
The data plane URI of the blob service of the storage account, using the HTTPS scheme. | https://<storage_account_name>.blob.core.windows.net |
AzureWebJobsStorage__queueServiceUri |
The data plane URI of the queue service of the storage account, using the HTTPS scheme. | https://<storage_account_name>.queue.core.windows.net |
AzureWebJobsStorage__tableServiceUri |
The data plane URI of a table service of the storage account, using the HTTPS scheme. | https://<storage_account_name>.table.core.windows.net |
Common properties for identity-based connections may also be set as well.
If you are configuring "AzureWebJobsStorage" using a storage account that uses the default DNS suffix and service name for global Azure, following the https://<accountName>.blob/queue/file/table.core.windows.net
format, you can instead set AzureWebJobsStorage__accountName
to the name of your storage account. The endpoints for each storage service will be inferred for this account. This will not work if the storage account is in a sovereign cloud or has a custom DNS.
Setting | Description | Example value |
---|---|---|
AzureWebJobsStorage__accountName |
The account name of a storage account, valid only if the account is not in a sovereign cloud and does not have a custom DNS. This syntax is unique to "AzureWebJobsStorage" and cannot be used for other identity-based connections. | <storage_account_name> |
You will need to create a role assignment that provides access to the storage account for "AzureWebJobsStorage" at runtime. Management roles like Owner are not sufficient. The Storage Blob Data Owner role covers the basic needs of Functions host storage - the runtime needs both read and write access to blobs and the ability to create containers. Several extensions use this connection as a default location for blobs, queues, and tables, and these uses may add requirements as noted in the table below. You may need additional permissions if you use "AzureWebJobsStorage" for any other purposes.
Extension | Roles required | Explanation |
---|---|---|
No extension (host only) | Storage Blob Data Owner | Used for general coordination, default key store |
Azure Blobs (trigger only) | All of: Storage Account Contributor, Storage Blob Data Owner, Storage Queue Data Contributor |
The blob trigger internally uses Azure Queues and writes blob receipts. It uses AzureWebJobsStorage for these, regardless of the connection configured for the trigger. |
Azure Event Hubs (trigger only) | (no change from default requirement) Storage Blob Data Owner |
Checkpoints are persisted in blobs using the AzureWebJobsStorage connection. |
Timer trigger | (no change from default requirement) Storage Blob Data Owner |
To ensure one execution per event, locks are taken with blobs using the AzureWebJobsStorage connection. |
Durable Functions | All of: Storage Blob Data Contributor, Storage Queue Data Contributor, Storage Table Data Contributor |
Durable Functions uses blobs, queues, and tables to coordinate activity functions and maintain orchestration state. It uses the AzureWebJobsStorage connection for all of these by default, but you can specify a different connection in the Durable Functions extension configuration. |
Reporting Issues
Item | Description | Link |
---|---|---|
Runtime | Script Host, Triggers & Bindings, Language Support | File an Issue |
Templates | Code Issues with Creation Template | File an Issue |
Portal | User Interface or Experience Issue | File an Issue |
Next steps
For more information, see the following resources:
Feedback
Submit and view feedback for