This chapter covers the Azure Cosmos DB Change Feed, a critical feature for building real-time event-driven architectures. On the AZ-204 exam, Change Feed topics appear in approximately 10–15% of questions related to Storage (Objective 2.1), often integrated with Azure Functions or the Change Feed Processor library. You will be tested on how to configure, consume, and scale change feed processing, including lease management, ordering guarantees, and performance considerations. Mastering this topic is essential for scenarios requiring reactive workflows, data replication, or materialized views.
Jump to a section
Imagine a massive warehouse with shelves labeled by container (Cosmos DB container). Every time a product (document) is added, updated, or deleted, a worker (the Change Feed processor) records the change on a clipboard (the change feed) in the exact order it happened. The clipboard is stored in a secure office (the lease container) and each change is noted with a timestamp and a sequence number (_ts and _lsn). Multiple workers can read the clipboard simultaneously, but each worker (consumer) has their own bookmark (lease) so they know which changes they've already processed. If a worker wants to see only new changes, they start from the last bookmark. If they want to replay everything, they start from the beginning of the clipboard. The warehouse manager (Azure Functions or SDK) can assign different sections of the clipboard to different workers using a strategy called 'range partitioning' so that no two workers process the same change. This is exactly how Cosmos DB Change Feed works—it's an append-only log of all document changes, ordered by modification time, and can be consumed in parallel by multiple readers.
What is the Change Feed?
Azure Cosmos DB Change Feed is a persistent, append-only log of all document-level changes (inserts, updates, and deletes) within a container. It captures changes in the order they occur (by modification timestamp) and exposes them via a sorted, paginated feed. The Change Feed is not a separate store—it is a logical representation of the container's write-ahead log, and it is automatically available for any container that is configured with a partition key.
Why It Exists
Traditional databases require polling or triggers to detect changes, which is inefficient and introduces latency. The Change Feed provides a push-based mechanism that enables event-driven architectures without custom change-tracking code. It is the foundation for patterns like:
Materialized views or search indexes (e.g., updating Azure Cognitive Search)
Real-time analytics pipelines (e.g., streaming to Azure Synapse)
Cross-region replication (multi-master uses change feed internally)
Triggering serverless compute (Azure Functions)
How It Works Internally
When a document is inserted, updated, or deleted in a container, Cosmos DB assigns a logical sequence number (_lsn) and a timestamp (_ts) to the change. The Change Feed is a sorted list of these changes, ordered by _ts ascending. The feed is partitioned by physical partitions—each physical partition maintains its own change feed segment. The Change Feed Processor (or Azure Functions binding) coordinates reading across partitions.
Key Components
Lease Container: A separate container (usually named 'leases') that stores processing state (checkpoints). Each consumer (or 'host') has its own lease document per partition, tracking the last processed change.
Feed Container: The source container whose changes you want to consume.
Change Feed Processor: A client-side library that orchestrates reading the change feed across multiple consumers, handling partition distribution and lease renewal.
Azure Functions Binding: A serverless trigger that automatically scales and manages leases.
Defaults and Timers
Polling Interval: The Change Feed Processor polls for new changes every 100ms by default (configurable via WithPollInterval).
Lease Expiration: Leases expire after 60 seconds of inactivity (default). If a host crashes, another host takes over after this timeout.
Max Items per Page: The default page size is 100 items. You can increase it up to 1000 via MaxItemCount in the query options.
Change Feed Mode: There are two modes: Latest (default) returns only the latest change for a document; All versions and deletes (preview) returns all intermediate changes and deletes.
Configuration and Verification
To read the Change Feed programmatically (using .NET SDK):
string connectionString = "AccountEndpoint=https://myaccount.documents.azure.com:443/;AccountKey=mykey==";
CosmosClient client = new CosmosClient(connectionString);
Container feedContainer = client.GetContainer("mydb", "mycontainer");
Container leaseContainer = client.GetContainer("mydb", "leases");
ChangeFeedProcessor processor = feedContainer
.GetChangeFeedProcessorBuilder("myprocessor", HandleChangesAsync)
.WithInstanceName("myhost")
.WithLeaseContainer(leaseContainer)
.WithStartTime(DateTime.MinValue.ToUniversalTime()) // from beginning
.Build();
await processor.StartAsync();To verify: Check the lease container—each partition should have a lease document with LeaseToken, ContinuationToken (the last processed change's LSN), and Owner (the host name).
Interaction with Related Technologies
Azure Functions: The CosmosDBTrigger attribute automatically creates a Change Feed Processor. It separates the feed container and lease container. The trigger can be configured with LeaseCollectionPrefix for multi-function scenarios.
Azure Event Hubs: Change Feed is often paired with Event Hubs for high-throughput event ingestion. However, Change Feed provides exactly-once semantics per partition, whereas Event Hubs offers at-least-once.
Azure Stream Analytics: Can consume Change Feed via a custom input binding (preview).
Performance Considerations
Throughput: The Change Feed does not consume RUs for reading; it only consumes RUs for writing to the lease container (one write per checkpoint).
Scaling: For high-throughput containers (e.g., 10000 RU/s), ensure the lease container has sufficient RU/s (usually 400 RU/s is enough for up to 10 partitions).
Deletes: By default, deletes are not captured in the Change Feed (they produce a 'tombstone' that is not returned). To capture deletes, enable 'All versions and deletes' mode (preview) or use a soft-delete pattern.
Ordering: Changes within a partition key range are ordered by _ts. Across partitions, there is no global order.
Exam Trap: Change Feed vs. Change Tracking
Many candidates confuse Change Feed with Azure SQL Database's Change Tracking or Change Data Capture. Change Feed is specific to Cosmos DB and does not require schema changes or triggers. Also, note that Change Feed does not support filtering by document content—you must filter in your consumer code.
Code Example: Azure Function with Change Feed
[FunctionName("ProcessChanges")]
public static void Run([CosmosDBTrigger(
databaseName: "mydb",
collectionName: "mycontainer",
ConnectionStringSetting = "CosmosDBConnection",
LeaseCollectionName = "leases",
CreateLeaseCollectionIfNotExists = true)]IReadOnlyList<Document> documents,
ILogger log)
{
if (documents != null && documents.Count > 0)
{
log.LogInformation($"Documents modified: {documents.Count}");
// Process each document
}
}Key Values to Memorize
Default polling interval: 100ms
Lease expiration: 60 seconds
Default max items per page: 100
Maximum items per page: 1000
Lease collection throughput: minimum 400 RU/s recommended
Summary of Mechanism
The Change Feed is a sorted, per-partition log of document changes. The Change Feed Processor uses a lease container to coordinate multiple consumers. Each consumer owns a set of partitions and advances its lease after successfully processing a batch. If a consumer fails, its leases expire and are reassigned. This provides fault-tolerant, at-least-once processing with ordering guarantees within a partition.
Create Lease Container
Before reading the change feed, you must have a lease container (usually named 'leases') in the same Cosmos DB account or a separate one. This container stores checkpoint information for each partition. It must have a partition key defined as '/id' (or any string field). The lease container should have at least 400 RU/s to handle the write load from checkpoint updates. You can create it via Azure Portal, CLI, or SDK.
Initialize Change Feed Processor
Using the Cosmos DB SDK (e.g., .NET V3), create a `ChangeFeedProcessor` instance by calling `GetChangeFeedProcessorBuilder` on the feed container. Provide a processor name (unique per logical consumer), a delegate to handle changes, and the lease container. Optionally set start time via `WithStartTime` (use `DateTime.MinValue` to read from beginning). Call `Build()` and `StartAsync()` to begin processing.
Lease Acquisition and Distribution
When the processor starts, it reads the lease container to discover existing leases. Each host (instance) attempts to acquire leases for partitions. By default, leases are distributed evenly across hosts using a 'range' strategy. A lease document contains the `LeaseToken` (partition key range id), `ContinuationToken` (last processed LSN), and `Owner` (host name). The host updates the lease after processing a batch.
Read Changes from Feed
The processor polls the feed container's change feed for each owned partition. It uses the continuation token to request changes after the last checkpoint. The feed returns a batch of documents (up to `MaxItemCount`). The documents include metadata like `_ts` and `_lsn`. The processor calls the user delegate with the batch. After successful processing, it writes a new checkpoint to the lease container (updating the `ContinuationToken`).
Lease Renewal and Failure Handling
Each host periodically renews its leases (default every 5 seconds) to indicate it is alive. If a host crashes, the lease expires after 60 seconds. Another host (or the same host after restart) will acquire the expired lease and resume processing from the last checkpoint. This ensures exactly-once processing per partition (at-least-once overall). The `WithLeaseAcquireInterval` and `WithLeaseExpirationInterval` can be configured.
Scenario 1: Real-Time Search Indexing
A large e-commerce platform uses Cosmos DB as its primary product catalog. To provide fast full-text search, they maintain an Azure Cognitive Search index. They deploy an Azure Function with a CosmosDBTrigger that reads the Change Feed and pushes updates to the search index. The function is scaled out to 10 instances. The lease container is configured with 1000 RU/s to handle the checkpoint write load. Initially, they forgot to set CreateLeaseCollectionIfNotExists = true, causing deployment failures. After fixing, they noticed that deletes were not reflected in search because the default Change Feed mode ignores deletes. They implemented a soft-delete pattern (setting an isDeleted flag) to capture deletions. Performance tip: they set MaxItemsPerInvocation to 500 to reduce function invocations.
Scenario 2: Multi-Region Data Aggregation
A financial services company aggregates transaction data from multiple regions into a central analytics store. Each region has its own Cosmos DB container. They use Change Feed Processor instances in each region to stream changes to an Azure Event Hub, which then feeds into Azure Synapse. The challenge was ordering: since changes across regions are not globally ordered, they added a timestamp field and used a session window in Synapse. They also discovered that the Change Feed Processor's default polling interval of 100ms was too aggressive for their low-throughput containers, causing unnecessary RU consumption on the lease container. They increased the polling interval to 1 second via WithPollInterval(TimeSpan.FromSeconds(1)).
Scenario 3: Materialized Views for Reporting
A SaaS company needs real-time dashboards that aggregate data from multiple containers. They use Change Feed to maintain a materialized view container that denormalizes data. They deploy a .NET Core microservice that hosts the Change Feed Processor. Initially, they used a single instance, which became a bottleneck. They scaled out to 4 instances, but experienced duplicate processing because lease distribution was uneven. They fixed it by ensuring all instances used the same processor name and lease container prefix. They also configured WithMaxItems(100) to control batch size. Common mistake: they forgot to set WithStartTime for new deployments, causing the processor to start from the current time and miss historical data. They now always set WithStartTime(DateTime.MinValue.ToUniversalTime()) for backfill scenarios.
When misconfigured, common issues include: lease container running out of RU/s (throttling), lease expiration causing frequent rebalancing, and missing deletes. Always monitor the lease container's request units and set appropriate throughput.
What AZ-204 Tests on Change Feed
The exam objectives under 'Store data in Azure Cosmos DB' (2.1) include: 'Implement the Change Feed by using the Change Feed Processor and Azure Functions'. Specifically, you need to know:
How to configure the Change Feed Processor with SDK (builder pattern)
How to create an Azure Function with CosmosDBTrigger
Lease container requirements (partition key, throughput)
Change Feed modes (latest vs all versions and deletes)
Ordering guarantees (per partition key range)
How to handle deletes (soft-delete or preview mode)
Common Wrong Answers and Why
'Change Feed captures all changes including deletes by default' – WRONG. Default mode only captures updates and inserts. Deletes are not returned unless using preview 'All versions and deletes' mode or soft-delete.
'Change Feed provides global ordering across all documents' – WRONG. Ordering is only guaranteed within a partition key range. Cross-partition ordering is not guaranteed.
'You must enable Change Feed on each container manually' – WRONG. Change Feed is automatically enabled for all containers with a partition key. No manual enablement needed.
'The lease container can be the same as the feed container' – WRONG. The lease container must be a separate container. Using the same container will cause conflicts and is not supported.
Exam Numbers and Terms
Default polling interval: 100 ms
Lease expiration: 60 seconds
Maximum items per page: 1000 (default 100)
Lease container partition key: '/id' (recommended)
Processor method: GetChangeFeedProcessorBuilder
Azure Functions attribute: CosmosDBTrigger
Property to set start time: WithStartTime
Mode for deletes: AllVersionsAndDeletes (preview)
Edge Cases and Exceptions
Throughput spikes: If the feed container has high write throughput, the Change Feed Processor may fall behind. Scale out by adding more instances. The lease container may also need more RU/s.
Empty lease container: When starting for the first time with no leases, the processor will create leases for all partitions. Ensure the lease container has enough RU/s for initial write burst.
Function scaling: Azure Functions with CosmosDBTrigger scale based on number of partitions. Each function instance can own multiple partitions. The trigger uses a lease renewal mechanism similar to the SDK.
Backfill: To read historical changes, set WithStartTime to a past timestamp. This is often used for initial load.
How to Eliminate Wrong Answers
If an answer says 'Change Feed must be enabled via portal', eliminate it – it's automatic.
If an answer says 'Ordering is guaranteed across all documents', eliminate it – only per partition.
If an answer suggests using the same container for leases, eliminate it – must be separate.
If an answer claims deletes are captured by default, eliminate it – they are not.
Focus on understanding the lease mechanism, the SDK builder pattern, and the Azure Functions trigger configuration. Practice writing code snippets for both.
Change Feed is automatically enabled for all Cosmos DB containers with a partition key.
Default Change Feed mode captures only inserts and updates; deletes require preview mode or soft-delete.
Ordering of changes is guaranteed only within a partition key range, not globally.
Lease container must be a separate container with partition key '/id' and sufficient throughput (minimum 400 RU/s).
Default polling interval is 100 ms; default lease expiration is 60 seconds.
Change Feed Processor provides at-least-once delivery; duplicates can occur if checkpointing fails.
Azure Functions CosmosDBTrigger uses the same underlying Change Feed Processor library.
To read historical changes, use `WithStartTime` (SDK) or `StartFromBeginning` (Functions).
Maximum items per page is 1000 (default 100).
Change Feed does not consume RUs for reading; only writes to lease container consume RUs.
These come up on the exam all the time. Here's how to tell them apart.
Change Feed Processor (SDK)
Requires manual host management and scaling
More control over lease configuration (poll interval, expiration)
Can run in any .NET application, not limited to Functions
Supports custom start time and change feed modes explicitly
Lease distribution strategy can be customized (e.g., manual)
Azure Functions CosmosDBTrigger
Serverless, automatically scales based on partition count
Simpler setup with attribute-based configuration
Tightly integrated with Azure Functions runtime
Start time is set via `StartFromBeginning` property (bool) or `StartFromTime`
Lease management is abstracted; less control over fine-tuning
Mistake
Change Feed captures all document changes including deletes by default.
Correct
Default mode only captures inserts and updates. Deletes are not included unless you enable the preview 'All versions and deletes' mode or implement a soft-delete pattern.
Mistake
You must manually enable Change Feed on each container.
Correct
Change Feed is automatically enabled for all Cosmos DB containers that have a partition key defined. No manual configuration is required.
Mistake
Change Feed provides global ordering of changes across the entire container.
Correct
Ordering is guaranteed only within a logical partition key range. Changes across different partitions are not globally ordered.
Mistake
The lease container can be the same as the feed container.
Correct
The lease container must be a separate container. Using the same container is not supported and will cause conflicts.
Mistake
Change Feed Processor guarantees exactly-once delivery for every change.
Correct
It provides at-least-once delivery per partition. Duplicates are possible if a consumer crashes after processing but before checkpointing.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
By default, the Change Feed does not include deletes. To capture deletes, you have two options: (1) Enable the preview feature 'All versions and deletes' mode, which returns all intermediate versions and delete markers. This is set via `WithChangeFeedMode(ChangeFeedMode.AllVersionsAndDeletes)` in the SDK. (2) Implement a soft-delete pattern: instead of deleting the document, set a `deleted` flag to true and update the document. Then filter on that flag in your consumer. The preview mode is recommended for new applications but is not yet GA.
Change Feed is the logical log of changes in a Cosmos DB container. Change Feed Processor is a client-side library that simplifies reading the Change Feed in a distributed, fault-tolerant manner. It uses a lease container to coordinate multiple consumers and provides checkpointing. Without the processor, you would have to manually paginate and track continuation tokens. The processor is the recommended way to consume the Change Feed.
Yes. In the Change Feed Processor SDK, use the `WithStartTime` method and pass a `DateTime` value. For example, `WithStartTime(DateTime.UtcNow.AddHours(-1))` reads changes from one hour ago. In Azure Functions, set `StartFromBeginning = false` and `StartFromTime = DateTime.UtcNow.AddHours(-1)` in the trigger attribute. Note that the Change Feed only retains changes for a limited time (default 7 days for the latest mode, configurable via the container's time-to-live setting).
You scale by adding more consumer instances (hosts). The Change Feed Processor distributes partitions across instances automatically. Each instance processes a subset of partitions. For Azure Functions, scaling is automatic—the runtime creates new instances based on the number of partitions. Ensure the lease container has enough throughput to handle checkpoint writes from all instances. Also, consider increasing `MaxItemsPerInvocation` to reduce the number of function invocations.
Reading the Change Feed itself does not consume RUs from the feed container. However, writing checkpoints to the lease container consumes RUs (approximately 1 RU per checkpoint). The lease container must have sufficient provisioned throughput to handle the checkpoint write load. For a high-throughput scenario, monitor the lease container's RU consumption and scale it accordingly.
If a consumer crashes, its leases will expire after the lease expiration interval (default 60 seconds). Other running consumers will detect the expired leases and acquire them, resuming processing from the last checkpoint. This ensures that no changes are lost, but duplicates may occur if the crashed consumer had processed changes but not yet checkpointed. The system provides at-least-once delivery.
The Change Feed does not support server-side filtering. You must filter in your consumer code after receiving the batch of changes. For example, you can check a document property and skip processing if it doesn't match your criteria. This is a common pattern to reduce downstream load.
You've just covered Cosmos DB Change Feed — now see how well it sticks with free AZ-204 practice questions. Full explanations included, no account needed.
Done with this chapter?