Event Grid with Azure Functions

Azure Functions and Azure Event Grid work together as one of the most powerful combinations in serverless architecture. Event Grid detects something happening across Azure, and Azure Functions runs your code automatically in response — with no servers to manage and no idle cost when nothing is happening.

How the Integration Works

An Azure Function with an Event Grid trigger activates the moment Event Grid delivers an event to it. The function receives the event data as a parameter, runs its logic, and finishes. Azure handles all infrastructure, scaling, and retry coordination.
+-----------------------+
|   Event Source        |
|   (Blob Storage,      |
|    Resource Manager,  |
|    Custom App)        |
+----------+------------+
           |
           | Sends event
           v
+-----------------------+
|   Event Grid Topic    |
|   + Subscription      |
+----------+------------+
           |
           | Delivers event payload
           v
+-----------------------+
|   Azure Function      |   <-- Your code runs here
|   (Event Grid         |
|    Trigger)           |
|                       |
|   Input: event object |
|   Logic: your code    |
|   Output: any action  |
+-----------------------+

Two Ways to Connect Event Grid to Azure Functions

Option 1 – Event Grid Trigger (Recommended)

The Event Grid Trigger is purpose-built for this integration. Event Grid pushes the event directly to the function. The function URL is registered automatically in the subscription.

Option 2 – Webhook Trigger via HTTP Trigger

You can also use an HTTP-triggered function as a webhook endpoint in an Event Grid subscription. This gives more control over the HTTP response but requires manual validation handling.

The Event Grid Trigger handles validation automatically. For production use, choose the Event Grid Trigger.

Validation Handshake Explained

When you create a new Event Grid subscription pointing to any endpoint (including an Azure Function using HTTP Trigger), Event Grid sends a validation event first. The endpoint must respond correctly before Event Grid delivers real events.
Step 1: Create Subscription
  Event Grid --> sends ValidationEvent to endpoint
  {
    "eventType": "Microsoft.EventGrid.SubscriptionValidationEvent",
    "data": {
      "validationCode": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6"
    }
  }

Step 2: Endpoint Responds
  Endpoint --> returns validationCode back to Event Grid
  {
    "validationResponse": "512d38b6-c7b8-40c8-89fe-f46f9e9622b6"
  }

Step 3: Subscription Becomes Active
  Event Grid --> now delivers real events

The Event Grid Trigger in Azure Functions handles this validation automatically. You write zero validation code.

Event Grid Trigger Function – Code Structure

C# Example

[FunctionName("ProcessBlobCreated")]
public static void Run(
    [EventGridTrigger] EventGridEvent eventGridEvent,
    ILogger log)
{
    log.LogInformation("Event type: {type}", eventGridEvent.EventType);
    log.LogInformation("Event subject: {subject}", eventGridEvent.Subject);

    // Parse the event data
    var blobData = eventGridEvent.Data.ToObjectFromJson<StorageBlobCreatedEventData>();
    log.LogInformation("Blob URL: {url}", blobData.Url);

    // Your business logic here
    // e.g., generate thumbnail, extract text, send notification
}

Python Example

import azure.functions as func
import logging
import json

def main(event: func.EventGridEvent):
    logging.info("Received event: %s", event.event_type)
    logging.info("Subject: %s", event.subject)

    # Access event data as a dictionary
    data = event.get_json()
    blob_url = data.get("url")
    logging.info("Blob URL: %s", blob_url)

    # Your business logic here

Real-World Example: Auto-Resize Images on Upload

Scenario

A web application stores user profile photos in Azure Blob Storage. Every uploaded photo needs a 200x200 thumbnail. Instead of resizing at upload time (which slows the upload API), Event Grid triggers a function to resize asynchronously.
FLOW DIAGRAM

User uploads photo.jpg
         |
         v
Azure Blob Storage (originals container)
         |
         | BlobCreated event fires
         v
Event Grid System Topic
         |
         | Filter: subject ends with ".jpg"
         v
Azure Function: ResizeThumbnail
         |
         | 1. Download original from URL in event data
         | 2. Resize to 200x200
         | 3. Upload thumbnail to "thumbnails" container
         | 4. Update database record with thumbnail URL
         v
Thumbnail saved: thumbnails/photo.jpg

Why This Pattern Works Well

AspectBenefit
Upload speedUser gets immediate response; resizing happens in background
CostFunction runs only when a photo uploads; zero idle cost
Scale100 simultaneous uploads trigger 100 function instances automatically
ReliabilityEvent Grid retries if function fails during resize

Handling Multiple Event Types in One Function

One function can handle different event types from the same subscription. Use a switch statement to route logic based on the event type.
[FunctionName("StorageEventRouter")]
public static void Run(
    [EventGridTrigger] EventGridEvent eventGridEvent,
    ILogger log)
{
    switch (eventGridEvent.EventType)
    {
        case "Microsoft.Storage.BlobCreated":
            HandleBlobCreated(eventGridEvent, log);
            break;

        case "Microsoft.Storage.BlobDeleted":
            HandleBlobDeleted(eventGridEvent, log);
            break;

        default:
            log.LogWarning("Unknown event type: {type}", eventGridEvent.EventType);
            break;
    }
}

Output Bindings from Event Grid Functions

An Azure Function triggered by Event Grid can also produce output — writing to storage, sending a message, or even publishing new events.
Event Grid Event
       |
       v
+------------------+
|  Azure Function  |
|                  |---> Write to Cosmos DB
|  Input:          |
|  Event payload   |---> Send Service Bus message
|                  |
|                  |---> Publish new Event Grid event
+------------------+

This chaining pattern lets you build complex workflows entirely from serverless functions reacting to events.

Scaling Behavior

Azure Functions scale out automatically based on the number of incoming events. Event Grid can deliver events to multiple function instances simultaneously. The platform manages concurrency.
Low traffic:
Event Grid --> 1 function instance

Medium traffic (50 events):
Event Grid --> 5 function instances (10 events each)

High traffic (500 events):
Event Grid --> 50 function instances (auto-scaled)

For Consumption Plan functions, each instance handles one event at a time. For Premium Plan functions, concurrency per instance is configurable.

Error Handling and Retries

When a function throws an unhandled exception, it returns a 500 error to Event Grid. Event Grid then retries the event delivery using exponential backoff. If the function keeps failing, the event eventually goes to the dead letter storage.
Function throws exception
         |
         | Returns HTTP 500
         v
Event Grid retries after 10 seconds
         |
         | Still fails
         v
Event Grid retries after 30 seconds
         |
         | Still fails (after 24 hours total)
         v
Event moved to Dead Letter Storage

Make your function code idempotent — running it twice with the same event should produce the same result. This prevents duplicate processing when Event Grid retries.

Best Practices

PracticeReason
Use Event Grid Trigger instead of HTTP TriggerAutomatic validation, cleaner code
Write idempotent functionsSafe against Event Grid retry duplicates
Keep function execution time short (under 5 minutes)Avoids timeout-based delivery failures
Log the event ID at the start of each functionMakes duplicate detection easier in logs
Enable dead letter storage on every subscriptionCaptures events that exhaust all retries
Use filter rules on subscriptionsReduces unnecessary function invocations

Summary

Azure Functions with Event Grid Trigger form a clean, scalable, serverless pattern. Event Grid detects changes across Azure services and pushes event data to a function. The function runs your business logic automatically, scales to handle any volume, and costs nothing when idle. Validation, retries, dead lettering, and scaling are all handled by the platform, so your code focuses entirely on the business logic.