Skip to content

Observable collection change streams

The observable-query hub can compare collection snapshots and send a ChangeSet describing added, replaced, and removed items. This is a transport-level comparison of query results, not a Chronicle event stream or a promise of durable replay.

Set transferMode on the hub subscription request. The modes below describe subject-backed collection emissions:

ModeFirst emissionLater emissions
Omitted (legacy)Full data plus change set (initial items added)Full data plus change set
fullFull data, no change setFull data, no change set
deltaFull data, no change setChange set; full data is null/omitted

Legacy additive deltas can reduce client reconciliation work, but sending both the snapshot and delta does not reduce payload bytes. Delta mode is the bandwidth-saving choice. Single-object and async-enumerable streams are not covered by this collection-delta contract. Direct per-query transports do not automatically inherit hub transfer-mode behavior.

For items with an Id property (case-insensitive), ChangeSetComputor compares identity and serialized JSON:

  • added: an identity appears in the new snapshot.
  • replaced: the identity remains but its serialized representation differs.
  • removed: an identity disappears; entries are removed items, not merely ID strings.

Without an Id property, full serialized JSON is used as the comparison key. Changes then appear as removal/addition rather than replacement. Use stable, unique identifiers when clients must reconcile collection state.

Previous delivered snapshot

Compare identities and JSON

Current intercepted snapshot

Added / replaced / removed

Apply subscription transfer mode

Client state

Illustrative payload fragment for a later delta-mode frame; the surrounding QueryResult metadata and hub envelope are intentionally not repeated:

{
"data": null,
"changeSet": {
"added": [{ "id": "account-2", "balance": 50 }],
"replaced": [{ "id": "account-1", "balance": 120 }],
"removed": [{ "id": "account-3", "balance": 0 }]
}
}

When no change set is present, treat data as the current snapshot. A reconnect/replacement subscription starts with a fresh snapshot; a change set is not a resume token. Under delta mode, do not replace client state with null just because the later frame omits full data.

ChangeSet has IEnumerable<object> properties Added, Replaced, and Removed. ChangeSetComputor takes JsonSerializerOptions; its Compute(previousItems, currentItems) returns a change set, and FindIdentityProperty(Type) locates the conventional ID property.

These APIs compare snapshots you supply; they do not observe a database independently. For database observation, see MongoDB-backed observable queries. For client reconstruction, see frontend change streams.