Event Schema & Filtering
Event Grid supports two event schemas and powerful filtering capabilities. Understanding both is essential for building efficient event-driven systems that only process the events they need.
Event Grid Schema vs CloudEvents 1.0
Event Grid supports two schemas for event structure:
| Feature | Event Grid Schema | CloudEvents 1.0 |
|---|---|---|
| Standard | Azure-proprietary | CNCF open standard |
| Portability | Azure-only | Multi-cloud compatible |
| Adoption | Default for Azure services | Growing industry standard |
| Header delivery | JSON body only | Supports HTTP headers + body |
| Required fields | id, topic, subject, eventType, eventTime, data, dataVersion | id, source, type, specversion |
Event Grid Schema — Full Example
{
"id": "9aeb0fdf-c01e-0131-0922-9eb54906e209",
"topic": "/subscriptions/sub-id/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/myacct",
"subject": "/blobServices/default/containers/images/blobs/photo.jpg",
"eventType": "Microsoft.Storage.BlobCreated",
"eventTime": "2024-03-15T14:22:13.7281928Z",
"data": {
"api": "PutBlob",
"clientRequestId": "4c5b-a2e8-3f1d",
"requestId": "9602e83f-0001-00e6-6208-4a0000000000",
"eTag": "0x8D4BCC2E4835CD0",
"contentType": "image/jpeg",
"contentLength": 524288,
"blobType": "BlockBlob",
"url": "https://myacct.blob.core.windows.net/images/photo.jpg",
"sequencer": "00000000000004420000000000028963"
},
"dataVersion": "",
"metadataVersion": "1"
}
Field-by-Field Explanation
| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier. Use for deduplication in your handler |
topic | string | Full Azure Resource Manager path of the event source. Set by Event Grid, not the publisher |
subject | string | Publisher-defined path describing what specifically changed. Used for filtering |
eventType | string | Registered event type (e.g., Microsoft.Storage.BlobCreated). Used for filtering |
eventTime | string | UTC time the event was generated by the provider |
data | object | Event-specific payload. Structure varies by event source |
dataVersion | string | Schema version of the data object. Set by the publisher |
metadataVersion | string | Schema version of the event metadata. Always "1" for Event Grid schema |
CloudEvents 1.0 Schema — Full Example
{
"specversion": "1.0",
"id": "9aeb0fdf-c01e-0131-0922-9eb54906e209",
"source": "/subscriptions/sub-id/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/myacct",
"type": "Microsoft.Storage.BlobCreated",
"time": "2024-03-15T14:22:13.7281928Z",
"subject": "/blobServices/default/containers/images/blobs/photo.jpg",
"datacontenttype": "application/json",
"data": {
"api": "PutBlob",
"clientRequestId": "4c5b-a2e8-3f1d",
"requestId": "9602e83f-0001-00e6-6208-4a0000000000",
"eTag": "0x8D4BCC2E4835CD0",
"contentType": "image/jpeg",
"contentLength": 524288,
"blobType": "BlockBlob",
"url": "https://myacct.blob.core.windows.net/images/photo.jpg",
"sequencer": "00000000000004420000000000028963"
}
}
CloudEvents Field Mapping
| CloudEvents Field | Event Grid Equivalent | Notes |
|---|---|---|
specversion | metadataVersion | Always "1.0" for CloudEvents |
source | topic | The event source identifier |
type | eventType | The event type string |
time | eventTime | When the event occurred |
subject | subject | Same — what specifically changed |
datacontenttype | (implicit) | MIME type of the data field |
id | id | Unique event identifier |
Subject Filtering (Prefix and Suffix)
Subject filters let you narrow events based on the subject field — typically a resource path.
# Only receive events for blobs in the "images" container
az eventgrid event-subscription create \
--name images-only \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--subject-begins-with "/blobServices/default/containers/images/"
# Only receive events for .jpg files
az eventgrid event-subscription create \
--name jpg-only \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--subject-ends-with ".jpg"
# Combine prefix AND suffix — images container, only PNG files
az eventgrid event-subscription create \
--name images-png \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--subject-begins-with "/blobServices/default/containers/images/" \
--subject-ends-with ".png"
Event Type Filtering
Filter by event type to only receive specific categories of events:
# Only BlobCreated events (ignore deletes, tier changes, etc.)
az eventgrid event-subscription create \
--name creates-only \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--included-event-types Microsoft.Storage.BlobCreated
# Multiple event types
az eventgrid event-subscription create \
--name creates-and-deletes \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--included-event-types Microsoft.Storage.BlobCreated Microsoft.Storage.BlobDeleted
Advanced Filtering (Data Field Filters)
Advanced filters let you filter on any field in the event, including nested data properties. This is the most powerful filtering mechanism.
Available Operators
| Operator | Description | Example Use |
|---|---|---|
NumberGreaterThan | Numeric comparison | File size > 1MB |
NumberLessThan | Numeric comparison | File size < 100KB |
NumberIn | Value in a set | Status code in [200, 201] |
StringContains | Substring match | URL contains "archive" |
StringBeginsWith | Prefix match | Subject starts with path |
StringEndsWith | Suffix match | Filename ends with ".csv" |
StringIn | Exact match in set | Content type in ["image/png", "image/jpeg"] |
BoolEquals | Boolean comparison | isSnapshot equals true |
IsNullOrUndefined | Null check | Field is missing |
IsNotNull | Existence check | Field exists |
CLI Examples with Advanced Filters
# Only events where content length is greater than 1MB (1048576 bytes)
az eventgrid event-subscription create \
--name large-files-only \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--advanced-filter data.contentLength NumberGreaterThan 1048576
# Only events where content type is an image
az eventgrid event-subscription create \
--name images-by-content-type \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--advanced-filter data.contentType StringIn "image/jpeg" "image/png" "image/gif"
# Only events from the PutBlob API (not CopyBlob or PutBlockList)
az eventgrid event-subscription create \
--name putblob-only \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--advanced-filter data.api StringIn "PutBlob"
Combining Multiple Filters
You can combine subject filters, event type filters, and multiple advanced filters. All conditions must be true (AND logic):
# Complex filter: BlobCreated + images container + JPEG content type + size > 500KB
az eventgrid event-subscription create \
--name complex-filter \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/handler" \
--included-event-types Microsoft.Storage.BlobCreated \
--subject-begins-with "/blobServices/default/containers/images/" \
--advanced-filter data.contentType StringIn "image/jpeg" \
--advanced-filter data.contentLength NumberGreaterThan 512000
Filter limits:
- Maximum 25 advanced filters per subscription
- Maximum 5 values per filter (for
Inoperators) - String values limited to 512 characters each
Choosing Which Schema to Use
| Choose Event Grid Schema when... | Choose CloudEvents when... |
|---|---|
| Building Azure-only solutions | Building multi-cloud or hybrid solutions |
| Using system topics (default output) | Integrating with non-Azure services |
| You want the simplest setup | You need industry-standard event format |
| Your team is Azure-focused | Your team works across cloud providers |
| You don't need portability | You want to avoid vendor lock-in |
# Create a custom topic that accepts CloudEvents
az eventgrid topic create \
--name my-cloudevents-topic \
--resource-group my-rg \
--location eastus \
--input-schema cloudeventschemav1_0
# Create subscription with CloudEvents delivery schema
az eventgrid event-subscription create \
--name my-sub \
--source-resource-id $TOPIC_ID \
--endpoint "https://my-api.azurewebsites.net/api/events" \
--event-delivery-schema cloudeventschemav1_0
Practical Examples: Filtering Blob Events
Process only CSV uploads in a data-lake container
az eventgrid event-subscription create \
--name csv-processor \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/ProcessCSV" \
--included-event-types Microsoft.Storage.BlobCreated \
--subject-begins-with "/blobServices/default/containers/data-lake/" \
--subject-ends-with ".csv"
Trigger thumbnail generation only for large images
az eventgrid event-subscription create \
--name thumbnail-gen \
--source-resource-id $STORAGE_ID \
--endpoint "https://my-func.azurewebsites.net/api/GenerateThumbnail" \
--included-event-types Microsoft.Storage.BlobCreated \
--subject-begins-with "/blobServices/default/containers/uploads/" \
--advanced-filter data.contentType StringBeginsWith "image/" \
--advanced-filter data.contentLength NumberGreaterThan 102400
Common Mistakes
- Case sensitivity — Subject filters are case-sensitive.
/blobServices/default/containers/Images/won't match/blobServices/default/containers/images/ - Missing leading slash — Subject paths for blob events always start with
/blobServices/default/containers/ - Too many advanced filters — Maximum 25 per subscription. If you need more, split into multiple subscriptions
- Filtering on missing fields — If a field doesn't exist in the event data, the filter evaluates to false. Use
IsNotNullto check existence first - Confusing input schema with delivery schema — Input schema is how events arrive at the topic; delivery schema is how they're sent to handlers
Key Takeaways
- Event Grid schema is Azure-native and simpler; CloudEvents 1.0 is the portable industry standard
- Subject filtering (prefix/suffix) is the fastest way to narrow events by resource path
- Event type filtering limits which categories of events you receive
- Advanced filters can match on any field including nested data properties using operators like StringContains, NumberGreaterThan, etc.
- All filter types combine with AND logic — every condition must be true
- Maximum 25 advanced filters per subscription with 5 values each
- Choose CloudEvents for multi-cloud portability; Event Grid schema for Azure-only simplicity
- Subject paths are case-sensitive — always verify the exact path format