Domain 2 β€” Module 4 of 8 50%
12 of 27 overall
Domain 2: Develop AI solutions by using Azure data management services Free ⏱ ~12 min read

Cosmos DB Change Feed: Real-Time Reactions

Detect and handle new or updated items in real time using the change feed processor. The pattern that powers async embeddings, materialised views, audit pipelines, and KEDA-driven scale-to-process workflows.

What the change feed is

Simple explanation

The change feed is a permanent, ordered log of every insert and update inside a Cosmos container. Whenever a document is created or modified, that event lands on the change feed in the partition’s order. You can read the log, react to events, and remember where you stopped β€” like reading a journal.

For AI apps, this enables patterns the platform makes easy: β€œevery time a new article is inserted, generate an embedding and update the doc”; β€œevery time an order document changes, recompute personalisation tags”; β€œevery audit event triggers a downstream alert.”

You read the change feed in two ways: a processor (push model) that delivers events to your callback continuously, or a pull model where your code asks for the next batch. The exam expects you to know the processor pattern.

The processor pattern

# Python β€” change feed processor for Cosmos DB
from azure.cosmos.aio import CosmosClient

async def handle_changes(context, changes):
    for doc in changes:
        if doc.get("kind") == "article" and not doc.get("embedding"):
            # New article without embedding β€” go generate one
            await embed_and_update(doc)

async def main():
    async with CosmosClient(URL, credential=CRED) as client:
        db = client.get_database_client("knowledge")
        feed_container = db.get_container_client("articles")
        lease_container = db.get_container_client("articles-leases")

        processor = await feed_container.get_change_feed_processor(
            processor_name="embedder",
            lease_container=lease_container,
            on_changes_delegate=handle_changes,
        )
        await processor.start()
        try:
            await asyncio.Event().wait()  # run forever
        finally:
            await processor.stop()

Three roles in this code:

RoleContainerPurpose
Monitored containerarticlesWhere the documents live and changes occur
Lease containerarticles-leasesStores cursor state per partition; needed for distributed processors
Processor hostYour workerMultiple instances coordinate via the lease container

Run the processor in three replicas? Cosmos partitions are leased across them automatically. One instance crashes? Its leases time out and rebalance to surviving instances. No code change.

Push vs pull

The processor is the recommended pattern for ongoing reactive work; pull is for explicit batch processing.
FeatureChange feed processor (push)Change feed pull model
Who drives the loopThe library β€” your callback receives batchesYour code β€” you call `query_items_change_feed` explicitly
Lease managementAutomatic via lease containerManual β€” you store continuation tokens
Best forLong-lived workers, partition rebalancing across replicas, the default choiceCustom apps that need precise cursor control or batch jobs
When the exam usually expects you to use thisEvent-driven workers, RAG embedding pipelines, materialised viewsBackfill scripts, snapshot-and-replay tools

Modes β€” latest version vs all versions and deletes

ModeWhat you seeWhere it matters
Latest version (default)The newest version of each changed document; deletes are NOT includedMost replication / projection workflows
All versions and deletesEvery intermediate version + delete tombstonesAudit trails, full event sourcing, compliance use cases
# Configure to include deletes (Python)
processor = await feed_container.get_change_feed_processor(
    processor_name="audit",
    lease_container=lease_container,
    on_changes_delegate=handle_changes,
    mode="AllVersionsAndDeletes",
)

Theo’s clinical assistant uses all versions and deletes so the audit table records every patient-record edit with full history. Mira’s embedding worker uses the default latest version β€” she only cares about the most recent state.

Common AI patterns

Pattern 1 β€” async embedding pipeline

Article created in Cosmos
   ↓ (change feed)
Embedder worker picks it up
   ↓
Calls Azure OpenAI for an embedding
   ↓
Updates the doc in place: writes /embedding field

The same container holds source content AND its embeddings. Documents missing /embedding come through the change feed; once the embedding is patched in, the change feed skips it (because kind filter rejects already-processed shape).

Pattern 2 β€” denormalised materialised views

Order doc updated
   ↓ (change feed)
Projection worker reads the new state
   ↓
Writes one or more rows in a flattened "order_summary" container

The summary container is partitioned for the query workload (e.g., /customerId) while the source is partitioned for the write workload (e.g., /orderId). The change feed keeps them aligned.

Pattern 3 β€” KEDA scaler triggers Container Apps

The Cosmos DB KEDA scaler watches the change-feed lag and scales replicas accordingly:

rules:
  - name: cosmos-cf-scale
    custom:
      type: azure-cosmosdb
      metadata:
        connectionFromEnv: COSMOS_CONNECTION_STRING
        databaseName: knowledge
        containerName: articles
        leaseContainerName: articles-leases
        eventCount: "100"

Translation: β€œfor every 100 unprocessed change-feed events, run one replica.” When Mira ingests 5,000 new articles, KEDA scales the embedder out, the worker chews through the backlog, and replicas drop back when the feed catches up.

Real-world example: Priya's loyalty pipeline

BeanCraft Coffee writes raw transactions into Cosmos’s transactions container. A change feed processor:

  1. Watches transactions (partitioned by /storeId)
  2. For each new transaction, calls Azure OpenAI to compute personalisation tags
  3. Writes the result into customer_summary (partitioned by /customerId)
  4. Lease container is transactions-leases

KEDA scales the processor on Service Bus during morning rush. The change feed and KEDA pair makes the same workload self-tuning all day.

Operational notes

ConcernWhat you do
Lease container needs throughput tooProvision RU/s on the lease container β€” it gets writes for every partition checkpoint
Processor name uniquenessTwo different processors (embedder, auditor) can read the same change feed independently as long as they use different processor_name (and ideally different lease containers)
DeletesDefault mode skips deletes. Use all versions and deletes if you need them
At-least-once deliveryYour handler must be idempotent β€” the same change can replay if a host crashes mid-batch
OrderGuaranteed within a partition, NOT across partitions

Key terms

Question

What is the Cosmos DB change feed?

Click or press Enter to reveal answer

Answer

A persistent, ordered log of all create and update operations within each logical partition of a container. Read it to react to changes β€” embed new docs, project to materialised views, audit edits. By default deletes are excluded; use 'all versions and deletes' mode to include them.

Click to flip back

Question

What's the difference between change feed processor and pull model?

Click or press Enter to reveal answer

Answer

Processor (push) β€” the library distributes partitions across instances, manages leases, and calls your handler with batches. Pull β€” your code asks for the next batch with continuation tokens you manage. Processor is the recommended pattern; pull is for batch / cursor-controlled jobs.

Click to flip back

Question

What is the lease container in change feed processor?

Click or press Enter to reveal answer

Answer

A separate Cosmos container that stores the cursor state for each partition (which doc has been processed, which instance owns the lease). Required for the processor pattern. Provision its own RU/s β€” it gets one write per partition checkpoint.

Click to flip back

Question

When should you use 'all versions and deletes' mode?

Click or press Enter to reveal answer

Answer

When you need to see every intermediate edit, including deletes β€” audit trails, full event sourcing, compliance scenarios. Default mode shows only the latest state of changed docs and skips deletes.

Click to flip back

Question

How does the Cosmos DB KEDA scaler use the change feed?

Click or press Enter to reveal answer

Answer

It monitors how many unprocessed change-feed events are queued in the lease container and scales replicas based on `eventCount` per replica. When the change feed has lag, KEDA scales the worker out; when it catches up, replicas scale back to zero.

Click to flip back

Knowledge check

Knowledge Check

Mira wants to embed every new article in Cosmos automatically. The pipeline must keep running across replica restarts and survive instance crashes. Which mechanism fits best?

Knowledge Check

Theo needs an audit trail that captures every patient-record edit, including deletes, with full version history. Which Cosmos change feed mode does he need?

Knowledge Check

Lin runs a change feed processor that calls a third-party API for each new doc. The API is occasionally slow and the processor host sometimes crashes mid-batch. What design constraint does Lin's handler need?