Azure Functions Triggers and Bindings

A deep dive into serverless event-driven architecture.

Table of Contents

Introduction

Azure Functions provide a powerful event-driven, serverless compute platform. The core of this platform lies in its ability to react to events and interact with other services through its robust trigger and binding model. This article explores the concepts, implementation, and benefits of triggers and bindings in Azure Functions.

Understanding triggers and bindings is crucial for designing efficient, scalable, and cost-effective serverless applications on Azure.

Triggers

A trigger is what causes a function to execute. It's an Azure resource that defines how a function is invoked. When the event defined by the trigger occurs, the Azure Functions runtime creates an instance of the function and passes event data to it.

Triggers are declarative; you define them in your function's configuration, typically in a function.json file or through attributes in your code.

Key characteristics of triggers:

  • Event Source: Triggers are connected to specific event sources (e.g., an HTTP request, a new message in a Service Bus queue, a blob being added to storage).
  • Invocation: They initiate the execution of your function code.
  • Input Data: Triggers often provide input data to the function based on the event that occurred.

Bindings

Bindings connect your function to other Azure services and external data sources or sinks. They simplify your code by abstracting away the complexities of interacting with these services.

Bindings are also declarative and can be configured for both input and output. An input binding makes data available to your function, while an output binding sends data from your function to another service.

Benefits of using bindings:

  • Reduced Boilerplate Code: You don't need to write explicit code to connect to services like Azure Blob Storage, Cosmos DB, or Service Bus.
  • Simplified Data Handling: Data is automatically serialized or deserialized based on the binding configuration.
  • Extensibility: A wide range of built-in bindings are available, and you can create custom bindings.

Trigger and Binding Relationship

Every Azure Function must have exactly one trigger. However, it can have multiple input and output bindings.

The trigger defines the event that starts the function's execution. Bindings then provide additional data to the function (input bindings) or allow the function to send data to other services (output bindings).

Consider a function triggered by a new blob in Azure Blob Storage. This is the trigger. The function might then read the content of that blob (an input binding) and write a processed version of the data to Azure Cosmos DB (an output binding).

Common Triggers

Azure Functions offers a rich set of built-in triggers to handle various event scenarios:

  • HTTP Trigger: Invokes a function when an HTTP request is received. Ideal for building web APIs and webhooks.
  • Timer Trigger: Executes a function on a schedule (e.g., every hour, daily). Useful for background tasks and scheduled jobs.
  • Blob Trigger: Fires when a new or updated blob is detected in Azure Blob Storage. Perfect for event-driven file processing.
  • Queue Trigger: Invokes a function when a message is added to an Azure Storage Queue. Great for decoupling background tasks.
  • Service Bus Trigger: Responds to messages arriving in Azure Service Bus queues or topics. Enables reliable messaging patterns.
  • Event Grid Trigger: Reacts to events published by Azure Event Grid. Offers a highly scalable event routing service.
  • Cosmos DB Trigger: Executes when documents are created or updated in an Azure Cosmos DB collection.

Common Bindings

Bindings enable seamless integration with a wide array of Azure services and external systems:

Input Bindings:

  • Azure Blob Storage: Read blob content directly into your function.
  • Azure Cosmos DB: Query documents from a Cosmos DB collection.
  • Azure Table Storage: Retrieve entities from a table.
  • Azure Queue Storage: Retrieve messages from a queue.
  • Service Bus: Retrieve messages from queues or topics.
  • Event Hubs: Consume events from Event Hubs.
  • HTTP Request: Access the incoming HTTP request details.

Output Bindings:

  • Azure Blob Storage: Write data to a blob.
  • Azure Cosmos DB: Save documents to a collection.
  • Azure Table Storage: Insert or update table entities.
  • Azure Queue Storage: Send a message to a queue.
  • Service Bus: Send messages to queues or topics.
  • Event Hubs: Send events to an Event Hub.
  • HTTP Response: Return an HTTP response from your function.

Declarative Configuration

Triggers and bindings are defined declaratively, reducing the amount of code you need to write. This configuration can be done in two primary ways:

1. function.json (for JavaScript, Python, PowerShell, and other non-.NET languages)

Each function app has a function.json file that defines the function's bindings. Here's an example of an HTTP-triggered function with a Blob output binding:


{
  "scriptFile": "../run.py",
  "bindings": [
    {
      "authLevel": "function",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "blob",
      "direction": "out",
      "name": "outputBlob",
      "path": "output-container/{name}.txt",
      "connection": "AzureWebJobsStorage"
    }
  ]
}
                

2. Attributes (for C#, F#, Java)

In .NET languages, attributes are used within the function code to define triggers and bindings. This approach offers stronger typing and better discoverability.


using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

public static class ProcessBlob
{
    [FunctionName("ProcessBlobHttp")]
    public static async Task Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        [Blob("output-container/{Query.name}.txt", FileAccess.Write, Connection = "AzureWebJobsStorage")] Stream outputBlob,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");

        string name = req.Query["name"];
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        string data = name ?? "world";

        using (StreamWriter writer = new StreamWriter(outputBlob))
        {
            await writer.WriteAsync($"Hello, {data}!");
        }

        return new OkResult();
    }
}
                

Custom Triggers and Bindings

While Azure Functions provides a comprehensive set of built-in triggers and bindings, you can also create your own. This allows you to integrate with virtually any service or protocol.

Custom bindings involve developing extensions for the Azure Functions runtime. This is a more advanced topic but offers immense flexibility for specialized integration scenarios.

Conclusion

Triggers and bindings are fundamental to the Azure Functions development model. They abstract away service integration complexities, enabling you to focus on writing business logic.

By leveraging the declarative nature of triggers and bindings, you can build robust, scalable, and event-driven applications efficiently. Explore the available triggers and bindings to unlock the full potential of serverless computing with Azure Functions.