Skip to content

ChangeStreamService ​

CE Change Data Capture: tail a shard's Raft log via gRPC server-side streaming.

Client reconnects with a ResumeToken to continue from a position it chose. At-least-once delivery. History is released only up to a position the client acknowledges with AcknowledgeSubscription.

Methods ​

Subscribe ​

Open a long-lived server-side streaming RPC that tails the Raft log.

The server streams a ChangeEvent for each log entry once the serving node has applied it; entries that are not committed yet are never sent. When caught up, the stream waits until the node applies another entry. The stream stays open until the client cancels or the connection drops.

On reconnect, pass the last received ResumeToken to resume without gaps. Omit resume_token (or set all fields to zero) to start from the oldest retained entry.

Every stream reads as a registered consumer: the request names the consumer and either registers it with an explicit retention policy (incarnation 0) or resumes a live registration (incarnation from the first stream). The registration outlives the connection: a STRICT one until CancelSubscription, a BOUNDED one until a declared bound is crossed. The response's initial metadata carries the registration's incarnation as x-coordinode-consumer-incarnation.

A token whose position the log no longer holds is refused with FAILED_PRECONDITION and ErrorInfo reason RETENTION_LOST (metadata requested_index, first_retained_index): the stream never resumes past a gap. A registration that has ended is refused with FAILED_PRECONDITION and reason CONSUMER_TERMINATED (metadata incarnation, reason, checkpoint); registering the id again starts a new incarnation.

Sending an event is not delivery: the registration keeps every entry from its acknowledged position on, so a stream resumed without a token starts there and re-sends what the client never acknowledged. A resume token chooses where reading starts and releases nothing.

Transport: Server-streaming gRPC only (no HTTP transcoding)

Request: SubscribeRequest

FieldTypeDescription
resume_tokenResumeTokenToken from the last received ChangeEvent.position. Omit (all-zero) to start from the oldest retained entry.
filtersCdcFiltersOptional filter to reduce bandwidth.
consumer_idstringThe consumer this stream reads as: globally unique, chosen by the client. Required.
incarnationuint640 registers the consumer anew with retention, starting at resume_token (or the oldest retained entry without one); refused with ALREADY_EXISTS while another incarnation of the id is live. Any other value resumes that live incarnation, and retention is ignored.
retentionConsumerRetentionRequired when registering (incarnation 0).

Response: stream ChangeEvent

FieldTypeDescription
tsuint64HLC commit timestamp of the entry, in wall-clock microseconds since the Unix epoch with logical increments inside one microsecond: the latest commit timestamp of the transactions it carries. 0 for an entry that carries none (membership, leader blank).
termuint64Term of the leader that wrote this entry.
log_indexuint64Raft log index. Monotonically increasing per shard.
shard_iduint32Shard that produced this entry.
is_migrationboolTrue if this entry was written during a shard migration (e.g. bulk data transfer). Most CDC consumers should skip migration entries.
opsChangeOp[]The mutations carried by this log entry. Empty for an entry that carries none, and for a progress event: entries up to position held nothing the stream's filters keep, so the client can acknowledge past them.
positionResumeTokenWhere the stream continues after this event: pass it on reconnect to resume here, and to AcknowledgeSubscription once the event is held.

AcknowledgeSubscription ​

State that the client holds, durably, every event of its subscription before position: the registration may stop protecting that history, and a stream resumed without a token starts at position. Only this call releases history; acknowledging an earlier position than a previous one changes nothing. Refused with INVALID_ARGUMENT for a position past what the serving node has applied (nothing that far was sent) or for another shard, and like CancelSubscription for an ended or unknown incarnation.

Request: AcknowledgeSubscriptionRequest

FieldTypeDescription
consumer_idstringThe consumer acknowledging.
incarnationuint64Its incarnation, from the Subscribe response metadata.
positionResumeTokenThe position of the last event the client no longer needs the source for: it holds the events durably, or it has durably taken their effect into the state it keeps (for example by reading the current state at a snapshot that covers this position). Everything up to it is acknowledged: the server may release that source for this consumer, a resume continues after it, and a BOUNDED consumer's progress lag is measured from it.

Response: AcknowledgeSubscriptionResponse

Empty response (no fields).

CancelSubscription ​

End a consumer's registration: it stops holding the log, and its incarnation is refused from then on. Refused with FAILED_PRECONDITION and reason CONSUMER_TERMINATED when the incarnation has already ended, and NOT_FOUND for an id never registered.

Request: CancelSubscriptionRequest

FieldTypeDescription
consumer_idstringThe consumer to cancel.
incarnationuint64The incarnation to cancel, from the Subscribe response metadata. A different incarnation of the same id is left alone.

Response: CancelSubscriptionResponse

Empty response (no fields).

Types ​

AcknowledgeSubscriptionRequest ​

FieldTypeDescription
consumer_idstringThe consumer acknowledging.
incarnationuint64Its incarnation, from the Subscribe response metadata.
positionResumeTokenThe position of the last event the client no longer needs the source for: it holds the events durably, or it has durably taken their effect into the state it keeps (for example by reading the current state at a snapshot that covers this position). Everything up to it is acknowledged: the server may release that source for this consumer, a resume continues after it, and a BOUNDED consumer's progress lag is measured from it.

AcknowledgeSubscriptionResponse ​

No fields.

BoundedRetention ​

Finite bounds after which the registration ends. Both limits are required and must be above zero.

FieldTypeDescription
max_progress_lag_msuint64Most age, in milliseconds, of the oldest log entry the consumer has not yet been sent.
max_retained_bytesuint64Most bytes of log the consumer's position may require the shard to keep.
liveness_timeout_msuint64Longest time, in milliseconds, without the consumer being connected and heartbeating. Absent: the registration does not end for being absent, only for the two limits above.

CancelSubscriptionRequest ​

FieldTypeDescription
consumer_idstringThe consumer to cancel.
incarnationuint64The incarnation to cancel, from the Subscribe response metadata. A different incarnation of the same id is left alone.

CancelSubscriptionResponse ​

No fields.

CdcFilters ​

Filters applied server-side before streaming events to the client.

FieldTypeDescription
edge_typesstring[]If non-empty, only deliver events that touch at least one adjacency or edge-property key whose edge type matches one of these strings. Example: ["FOLLOWS", "LIKES"] Leave empty to receive all edge types.
is_migrationboolWhen set: only deliver events whose is_migration flag equals this value. When absent (HasField returns false): deliver both migration and non-migration events.

ChangeEvent ​

A single applied Raft log entry delivered to the CDC consumer.

FieldTypeDescription
tsuint64HLC commit timestamp of the entry, in wall-clock microseconds since the Unix epoch with logical increments inside one microsecond: the latest commit timestamp of the transactions it carries. 0 for an entry that carries none (membership, leader blank).
termuint64Term of the leader that wrote this entry.
log_indexuint64Raft log index. Monotonically increasing per shard.
shard_iduint32Shard that produced this entry.
is_migrationboolTrue if this entry was written during a shard migration (e.g. bulk data transfer). Most CDC consumers should skip migration entries.
opsChangeOp[]The mutations carried by this log entry. Empty for an entry that carries none, and for a progress event: entries up to position held nothing the stream's filters keep, so the client can acknowledge past them.
positionResumeTokenWhere the stream continues after this event: pass it on reconnect to resume here, and to AcknowledgeSubscription once the event is held.

ChangeOp ​

A single storage mutation within a ChangeEvent.

FieldTypeDescription
typeChangeOpType—
partitionuint32Storage partition (see coordinode_storage::engine::partition::Partition).
keybytesStorage key. Format depends on partition type. For REMOVE_RANGE this carries the range's inclusive start bound.
valuebytesValue bytes. Empty for DELETE ops; carries the merge operand for MERGE. For REMOVE_RANGE this carries the range's exclusive end bound (the half-open range deleted is [key, value)).

ConsumerRetention ​

How long a consumer's registration protects the history it still needs. One of the two must be chosen; there is no default.

FieldTypeDescription
strictStrictRetentionProtection lasts until the consumer is cancelled. Missing heartbeats do not end it.
boundedBoundedRetentionProtection ends once one of the declared bounds is crossed.

ResumeToken ​

Position in a shard's Raft log used to resume after disconnect.

The token names one log index, segment_id + entry_offset: the next entry to deliver. It stays valid when the server rewrites its log files.

FieldTypeDescription
shard_iduint32Shard this stream targets. Always 0 in CE single-shard mode.
segment_iduint64Log index of the first entry of the segment that held the last delivered entry. 0 together with entry_offset 0 means "the oldest retained entry".
entry_offsetuint64Entries of that segment already delivered, counted from segment_id.

StrictRetention ​

Protection until cancellation.

No fields.

SubscribeRequest ​

FieldTypeDescription
resume_tokenResumeTokenToken from the last received ChangeEvent.position. Omit (all-zero) to start from the oldest retained entry.
filtersCdcFiltersOptional filter to reduce bandwidth.
consumer_idstringThe consumer this stream reads as: globally unique, chosen by the client. Required.
incarnationuint640 registers the consumer anew with retention, starting at resume_token (or the oldest retained entry without one); refused with ALREADY_EXISTS while another incarnation of the id is live. Any other value resumes that live incarnation, and retention is ignored.
retentionConsumerRetentionRequired when registering (incarnation 0).

Enums ​

ChangeOpType ​

ValueNumberDescription
CHANGE_OP_TYPE_UNSPECIFIED0—
INSERT1—
DELETE2—
MERGE3—
NOOP4—
RAFT_ENTRY5—
RAFT_TRUNCATION6—
REMOVE_RANGE7Delete every key in the half-open range [key, value) of partition with a single range tombstone. Emitted for a dense contiguous run of deleted keys (run-length coalescing) or a whole-prefix DROP; the range covers only keys that are all being deleted, never a surviving key in a gap.