Azure Functions — All Trigger Types

Responding to Events from Azure Services


Introduction

Azure Functions are event-driven, meaning they execute in response to various triggers from Azure services and external sources. Understanding the different trigger types is essential for building serverless applications that respond to the right events at the right time.

This comprehensive guide covers:

  • Trigger overview — Complete list of available triggers
  • Implementation details — Code examples for each trigger type
  • Configuration options — How to configure triggers
  • Use cases — When to use each trigger type
  • Best practices — Optimizing trigger usage

Trigger Overview

Available Triggers

TriggerServiceUse CaseProcessing Mode
HTTPBuilt-inWeb APIs, webhooksSynchronous
TimerBuilt-inScheduled jobsTime-based
Blob StorageAzure StorageFile processingEvent-driven
Queue StorageAzure StorageMessage processingPolling
Service BusService BusEnterprise messagingPolling
Event GridEvent GridEvent routingPush
Event HubsEvent HubsHigh-throughput streamingPolling
Cosmos DBCosmos DBNoSQL change feedPolling
SendGridSendGridEmail eventsPush
TwilioTwilioSMS/webhook eventsPush
WebhookExternalExternal triggersPush

HTTP Trigger

Web API Endpoint

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

public class OrderFunctions
{
    [FunctionName("GetOrders")]
    public IActionResult GetOrders(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
    {
        var orders = new[] { new { Id = 1 }, new { Id = 2 } };
        return new OkObjectResult(orders);
    }
    
    [FunctionName("CreateOrder")]
    public async Task<IActionResult> CreateOrder(
        [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
    {
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        return new CreatedResult($"/orders/123", new { status = "created" });
    }
}

Webhook Handler

[FunctionName("GitHubWebhook")]
public async Task<IActionResult> GitHubWebhook(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req)
{
    string signature = req.Headers["X-Hub-Signature-256"];
    string body = await req.ReadAsStringAsync();
    
    // Verify webhook signature
    if (!VerifySignature(signature, body))
        return new UnauthorizedResult();
    
    var payload = JsonSerializer.Deserialize<GitHubPayload>(body);
    
    if (payload.Action == "opened")
    {
        // Process the event
    }
    
    return new OkResult();
}

Authorization Levels

// Anonymous - no auth required
[HttpTrigger(AuthorizationLevel.Anonymous, "get")]

// Function - requires function key
[HttpTrigger(AuthorizationLevel.Function, "get")]

// Admin - requires admin key
[HttpTrigger(AuthorizationLevel.Admin, "get")]

// Custom - use specific key
[HttpTrigger(AuthorizationLevel.Function, "get", Name = "MyFunction")]

Timer Trigger

Scheduled Job

[FunctionName("DailyReport")]
public void Run([TimerTrigger("0 0 8 * * *")] TimerInfo myTimer)
{
    Console.WriteLine($"Report job executed at: {DateTime.Now}");
    Console.WriteFunction($"Next run: {myTimer.Next}");
    
    // Run daily tasks
    GenerateReport();
}

CRON Expressions

┌─────────────────┬─────────────────────────────────────┐
│ Expression      │ Description                         │
├─────────────────┼─────────────────────────────────────┤
│ 0 0 * * * *     │ Every day at midnight               │
│ 0 */15 * * * *  │ Every 15 minutes                    │
│ 0 0 * * 1-5     │ Weekdays at midnight                │
│ 0 0 1 * *       │ First day of every month            │
│ 0 0 8 * * 1-5   │ Weekdays at 8 AM                    │
│ 0 */30 * * * *  │ Every 30 minutes                    │
└─────────────────┴─────────────────────────────────────┘

Timer with Configuration

[FunctionName("ScheduledCleanup")]
public async Task Run(
    [TimerTrigger("%CleanupSchedule%")] TimerInfo timer,
    ILogger log)
{
    // Schedule comes from configuration
    log.LogInformation($"Cleanup running at: {DateTime.Now}");
    
    // Long-running task with timeout
    var cts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
    await CleanupOldDataAsync(cts.Token);
}

Blob Storage Trigger

File Processing

[FunctionName("ProcessUploadedFile")]
public async Task ProcessUploadedFile(
    [BlobTrigger("uploads/{name}")] Stream fileStream,
    string name,
    ILogger log)
{
    log.LogInformation($"Processing file: {name}");
    
    using var reader = new StreamReader(fileStream);
    var content = await reader.ReadToEndAsync();
    
    // Process based on file type
    if (name.EndsWith(".csv"))
        await ProcessCsvAsync(content);
    else if (name.EndsWith(".json"))
        await ProcessJsonAsync(content);
}

Blob Metadata Access

[FunctionName("ProcessWithMetadata")]
public async Task Run(
    [BlobTrigger("uploads/{name}")] BlobClient blob,
    string name,
    ILogger log)
{
    // Get blob properties
    var properties = await blob.GetPropertiesAsync();
    
    log.LogInformation($"Size: {properties.Value.ContentLength}");
    log.LogInformation($"ContentType: {properties.Value.ContentType}");
    log.LogInformation($"Created: {properties.Value.CreatedOn}");
}

Queue Storage Trigger

Message Processing

[FunctionName("ProcessQueueMessage")]
public void ProcessQueueMessage(
    [QueueTrigger("orders")] string message,
    ILogger log)
{
    log.LogInformation($"Processing: {message}");
    
    var order = JsonSerializer.Deserialize<Order>(message);
    ProcessOrder(order);
}

POCO Message Types

public class OrderMessage
{
    public string OrderId { get; set; }
    public string CustomerId { get; set; }
    public decimal Total { get; set; }
}

[FunctionName("ProcessOrderMessage")]
public void ProcessOrderMessage(
    [QueueTrigger("orders")] OrderMessage message,
    ILogger log)
{
    log.LogInformation($"Processing order: {message.OrderId}");
    // Direct access to properties
}

Service Bus Trigger

Queue Processing

[FunctionName("ProcessServiceBusMessage")]
public void ProcessServiceBusMessage(
    [ServiceBusTrigger("orders", Connection = "ServiceBusConnection")] 
    ServiceBusReceivedMessage message,
    ILogger log)
{
    var body = message.Body.ToString();
    log.LogInformation($"Received: {body}");
    
    var order = JsonSerializer.Deserialize<Order>(body);
    await ProcessOrderAsync(order);
}

Topic Subscription

[FunctionName("ProcessTopicMessage")]
public void ProcessTopicMessage(
    [ServiceBusTrigger("orders-topic", "email-subscription", Connection = "ServiceBusConnection")] 
    ServiceBusReceivedMessage message,
    ILogger log)
{
    log.LogInformation($"Subject: {message.Subject}");
    log.LogInformation($"MessageId: {message.MessageId}");
    
    await SendEmailAsync(message);
}

Event Grid Trigger

Event Handler

[FunctionName("HandleBlobEvent")]
public void HandleBlobEvent(
    [EventGridTrigger] EventGridEvent eventGridEvent,
    ILogger log)
{
    log.LogInformation($"Event Type: {eventGridEvent.EventType}");
    log.LogInformation($"Subject: {eventGridEvent.Subject}");
    
    var data = eventGridEvent.Data;
    log.LogInformation($"Blob URL: {data["url"]}");
    
    if (eventGridEvent.EventType == "Microsoft.Storage.BlobCreated")
    {
        await ProcessNewBlobAsync(data["url"].ToString());
    }
}

CloudEvent Format

[FunctionName("HandleCloudEvent")]
public async Task HandleCloudEvent(
    [EventGridTrigger] CloudEvent cloudEvent,
    ILogger log)
{
    log.LogInformation($"Type: {cloudEvent.Type}");
    log.LogInformation($"Source: {cloudEvent.Source}");
    
    var data = JsonSerializer.Deserialize<MyEventData>(cloudEvent.Data.ToString());
    await ProcessEventAsync(data);
}

Event Hubs Trigger

Stream Processing

[FunctionName("ProcessEventHubEvents")]
public async Task ProcessEventHubEvents(
    [EventHubTrigger("telemetry", Connection = "EventHubConnection")] 
    EventData[] events,
    ILogger log)
{
    log.LogInformation($"Processing {events.Length} events");
    
    foreach (var eventData in events)
    {
        var body = Encoding.UTF8.GetString(eventData.Body);
        var telemetry = JsonSerializer.Deserialize<Telemetry>(body);
        
        await ProcessTelemetryAsync(telemetry);
    }
}

Batch Processing

[FunctionName("ProcessEventsBatch")]
public async Task ProcessEventsBatch(
    [EventHubTrigger("orders", Connection = "EventHubConnection", 
        ConsumerGroup = "processor")] 
    string[] messages,
    ILogger log)
{
    foreach (var message in messages)
    {
        var order = JsonSerializer.Deserialize<Order>(message);
        await ProcessOrderAsync(order);
    }
}

Cosmos DB Trigger

Change Feed Processing

[FunctionName("ProcessCosmosChanges")]
public async Task ProcessCosmosChanges(
    [CosmosDBTrigger(
        databaseName: "ordersdb",
        collectionName: "orders",
        Connection = "CosmosConnection",
        LeaseCollectionName = "leases")] 
    IReadOnlyList<Document> documents)
{
    foreach (var doc in documents)
    {
        var changeType = doc.GetPropertyValue<string>("operationType");
        
        if (changeType == "create")
        {
            await HandleOrderCreatedAsync(doc);
        }
        else if (changeType == "replace")
        {
            await HandleOrderUpdatedAsync(doc);
        }
    }
}

Binding Parameters

Connection Configuration

[FunctionName("WithConnections")]
public void Run(
    [BlobTrigger("container/{name}")] Stream blob,
    [QueueTrigger("myqueue")] string message,
    [ServiceBusTrigger("queue")] ServiceBusMessage sbMessage,
    ILogger log)
{
    // Each trigger can have its own connection
    // Configure in local.settings.json or app settings
}

Configuration in local.settings.json

{
  "Values": {
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=...",
    "ServiceBusConnection": "Endpoint=sb://...",
    "EventHubConnection": "Endpoint=sb://...",
    "CosmosConnection": "AccountEndpoint=..."
  }
}

Best Practices

PracticeDescription
Use binding attributesCleaner code with automatic deserialization
Configure connectionsUse named connections for multiple instances
Handle failuresReturn proper error codes or use retry policies
Scale appropriatelyConsider trigger type for scaling needs
Monitor triggersTrack invocation metrics

Trigger Selection Guide

Need HTTP endpoint?          → HTTP Trigger
Run on schedule?             → Timer Trigger
Process uploaded files?      → Blob Trigger
Handle queue messages?       → Queue/Service Bus Trigger
React to events?             → Event Grid Trigger
Process streaming data?      → Event Hubs Trigger
React to data changes?      → Cosmos DB Trigger

Related Topics


Azure Integration Hub - Intermediate Level