Skip to main content
Change Data Capture · New in 2.1.0

Every change, as a stream you can trust

Zaris captures every Put and Delete to the keyspace into a first-class, durable, ordered change feed. Read it from an OpenChangeFeed consumer, resume from a server-tracked cursor, and keep your caches, indexes, read models, and downstream systems in lock-step with the data.

How it works

One ordered feed, many consumers

Writes flow into a durable feed as they are applied. Named consumers read from it independently, filter at the source, and remember their place — so each downstream system stays in sync on its own schedule.

KeyspacePut / Deleteon any partitionChange feeddurable · orderedresumable cursorcaptured automaticallySearch indexCache / CDN invalidatorMaterialized viewAudit log / ETLnamed consumers · per-consumer offset & lag · prefix / op-kind filters
The consumer SDK

A few lines to a live projection

  • OpenChangeFeed(options, ct)Yields a stream of public ChangeEvents — the key, the op kind (Put/Delete), the value and its metadata (including TTL), and the source write time.
  • Resume, don't replaySet a durable ConsumerName and the server tracks your committed offset — reopen and pick up exactly where you stopped, even after a crash or a deploy. No manual commit.
  • Filter on the serverScope the feed by key-prefix and operation kind, so you receive only the changes you care about.
// A durable ConsumerName makes the server track this consumer's committed
// offset and lag — reopen the feed and it resumes automatically.
var options = new ChangeFeedOptions
{
    ConsumerName = "search-indexer",
    KeyPrefix    = "product:",                       // server-side filter
    Kinds        = new[] { FeedEventKind.Put, FeedEventKind.Delete },
};

var feed = (IZarisChangeFeedClient)client;           // the Zaris client is a feed consumer

await foreach (ChangeEvent e in feed.OpenChangeFeed(options, ct))
{
    if (e.IsDelete)
        await index.RemoveAsync(e.Key);
    else if (e.Value is { } bytes)                   // raw bytes of a plain-value write
        await index.UpsertAsync(e.Key, bytes, e.ExpiresAtUnixMs);
    // No manual commit: the named consumer's offset is tracked server-side.
}
Why CDC in Zaris

Not pub/sub. Not a polling job. A system of record for change.

Pub/sub and Streams are explicit and ephemeral — you publish to them. The change feed is implicit and durable: it records what actually happened to your data, in order, for whoever needs it.

Captured automatically

Every Put and Delete to the keyspace becomes an ordered change event — no application plumbing, no dual-writes. Unlike pub/sub or Streams, which you publish to explicitly, the feed is a faithful record of what actually changed.

Durable & ordered

Changes land in a durable, replicated feed in the order they were applied, so a consumer that comes up hours later still sees every change, exactly once per cursor, in sequence.

Resumable, per-consumer

Resume from a durable, server-tracked named-consumer offset. Each consumer has its own position, so one slow sink never holds the others back — and its lag is visible to operators.

Filtered at the source

Narrow the feed by key-prefix and operation kind on the server, so a consumer only receives the slice it cares about — less work on the wire and in your code.

Rich change events

Each ChangeEvent carries the key, the operation kind, the value and its metadata (including TTL), and a cursor token — everything a downstream system needs to apply the change and remember its place.

Secure & opt-in

The feed is read-authorized when security is on, and the whole capability is additive and opt-in — a store that never opens a feed is completely unaffected.

What you can build

Wire your data into everything downstream

Freshness

Cache & CDN invalidation

Drive precise invalidation from the source of truth — the moment a key changes, evict exactly the right cache or CDN entry instead of guessing with blanket TTLs.

Search

Keep a search index in sync

Stream Puts and Deletes straight into Elasticsearch, OpenSearch, or a vector store, so your index trails the data by milliseconds, not a nightly batch.

Read models

Materialized views & projections

Maintain denormalized read models and CQRS projections by folding the change stream forward — rebuild one from the start of the feed whenever the shape changes.

Compliance

Audit logs & event sourcing

Persist an ordered, durable trail of every mutation for audit, replay, and point-in-time reconstruction — captured at the store, not bolted onto each service.

Integration

Outbox & ETL to downstream systems

Use the feed as a reliable outbox: ship changes to a data warehouse, a message bus, or a partner system without dual-writes or a brittle polling job.

Real-time

Live UI subscriptions

Fan changes out to dashboards and clients so screens update the instant the underlying data moves — no polling loop, no staleness.

Turn your store into a stream of change

Change Data Capture is opt-in and additive — open a feed where you need one, leave every other store untouched.