Skip to content

Collection Types ​

DSM exposes three collection models. Choose based on the coordination problem, not by habit.

This page explains the semantic difference between the models. For method-level details and field-level defaults, use the Reference section.

Quick Mental Model ​

ModelCore shapeBest when
RegisterOne key maps to one replicated value.Metadata ordering is enough.
LeaseOne key has one active owner at a time.Fencing and ownership matter.
CRDTMany nodes update locally and merge state.Convergence matters more than single-writer order.

Decision Tree ​

Collection type decision tree

Side-By-Side View ​

ModelWrite patternUse when
RegisterOne value per key.Route hints, service-local metadata, and latest-value coordination.
LeaseOne active owner with renewal.Shard ownership, leader-style work assignment, and fencing.
CRDTConcurrent local updates with merge.Counters and mergeable state.

Register Collections ​

Use registers when you need replicated metadata keyed by an entry ID.

Typical workloads:

  • route hints
  • service-local feature state
  • cluster-visible operational metadata

Register collections are created with CollectionSpecBuilder.register(...).

java
CollectionSpecBuilder.<RouteHint>register(
		"shared",
		"gateway",
		"route-hints")
	.schemaId("route-hints/v1")
	.codec(new RouteHintCodec())
	.build();

Default builder behavior:

  • consistency tier: REGISTER
  • replication profile: embeddedRegister()
  • QoS profile: bestEffortMeta()
  • persistence profile: ephemeral()

Think of a register as: "I want the cluster to agree on the latest metadata value for this key." For example, edge-eu-west-1 may resolve to 10.1.0.8:8443; after node-a puts the route hint, the delta replicates and peers resolve the same key the same way.

Lease Collections ​

Use leases when a single owner must hold a responsibility at a point in time.

Typical workloads:

  • shard ownership
  • leader election
  • ownership handoff with fencing tokens

Lease collections are created with LeaseCollectionSpecBuilder.lease(...). They add lease term, renewal skew, expiry grace, and entity factory options.

java
LeaseCollectionSpecBuilder.<ShardOwner>lease(
				"shared",
				"worker",
				"shard-owner")
		.schemaId("shard-owner/v1")
		.codec(new ShardOwnerCodec())
		.entityFactory(ShardOwner::blank)
		.build();

Default builder behavior:

  • replication profile: embeddedLease()
  • QoS profile: controlCritical()
  • persistence profile: localDurable()
  • lease mode: AUTONOMOUS
  • lease term: 10s
  • renew skew: 3s
  • expiry grace: 500ms

Lease lifecycle

Use a lease when "who owns this key right now?" is the core question.

Lease Modes ​

ModeBehaviorUse when
AUTONOMOUSLocal runtime can acquire, renew, transfer, and release based on its current view.Availability matters and downstream fencing can tolerate partition-local decisions.
QUORUMLease mutations are rejected while membership is unstable or visible members cannot prove majority.Duplicate ownership during partitions is unacceptable.

In QUORUM mode the runtime waits for a stable membership size before calculating majority. While membership is settling, operations fail with membership-unstable; after the stable size is known, insufficient visible members fail with quorum-unavailable.

CRDT Collections ​

Use CRDTs when every node should be able to update locally and the cluster should converge through a merge function.

Typical workloads:

  • counters
  • monotonic aggregates
  • mergeable control-plane views

CRDT collections are created with CrdtCollectionSpecBuilder.crdt(...). They require an update codec, state codec, initial state, and merger.

java
CrdtCollectionSpecBuilder.<PnCounterUpdate, PnCounterState>crdt(
		"shared",
		"worker",
		"request-counter")
	.schemaId("request-counter/v1")
	.codec(new PnCounterUpdateCodec())
	.stateCodec(new PnCounterStateCodec())
	.initialState(PnCounterState.empty())
	.build();

Default builder behavior:

  • replication profile: embeddedCrdt()
  • QoS profile: standard()
  • persistence profile: localDurable()

CRDT convergence

Use a CRDT when local writes on multiple nodes should merge instead of fighting for one winning write.

Change Streams ​

Every collection handle exposes change streams for local observation and integration hooks. Treat them as an operational/event-observation surface, not as a durable event log.

Use ChangeStream forDo not use ChangeStream for
local audit hooksguaranteed message delivery
UI/devtool observationreplaying historical business events
federation live forwardingreplacing Kafka, Pulsar, or an outbox
cache invalidationsource-of-truth persistence

Bounded streams have overflow policies. If you cannot drop or fail fast safely, the consuming workflow probably needs a durable queue outside DSM.

How To Choose ​

Use this rule of thumb:

NeedChoose
Latest metadata value.Register
One active owner with fencing.Lease
Concurrent local updates.CRDT

If you are unsure, start with a register. Move to a lease only when ownership matters, and move to a CRDT only when multiple nodes truly need local writes.

Default Operational Profiles ​

  • Registers default to embedded register replication, best-effort metadata QoS, and ephemeral persistence.
  • Leases default to embedded lease replication, control-critical QoS, and local durable persistence.
  • CRDTs default to embedded CRDT replication, standard QoS, and local durable persistence.