Table of Contents

G-Set (Grow-Only Set)

This page is part of the documentation for Orleans.Lattice 9.9.0 (release line 9.9), built 2026-10-04. It is also published as markdown, with every table and list, at gset.md, and llms.txt lists every page.

tree.GSet(key) -> GSetAccessor, merge mode LatticeMergeMode.GSet.

Semantics

A G-Set is a set that only ever grows: elements can be added but never removed. Elements are opaque byte[] compared by content. The merge is plain set union, which is trivially commutative, associative, and idempotent, so concurrent active-active adds from any number of clusters all survive convergence and a re-delivered add is harmless.

Because it carries no dots and no tombstones, a G-Set is the minimal set primitive - the smallest, cheapest choice for append-only workloads such as tag sets, seen-ids, or an accumulating audience. When you need to remove elements, reach for the add-wins OR-Set or the remove-wins RW-Set instead.

Behaviour

Two concurrent G-Set adds meeting at their join. An order diagram shaped like a diamond, ordered by set inclusion. At the bottom is the empty set. Cluster A adds alice, reaching {alice}. Cluster B, at the same time, adds bob, reaching {bob}. Neither set contains the other. Merging takes the union, so both paths rise to the same top state, {alice, bob}.

Both clusters hold {alice, bob}. Union keeps every add, so no concurrent add is lost.

Merge is plain set union, which is commutative, associative, and idempotent.

sequenceDiagram
    participant A as Cluster A
    participant B as Cluster B
    A->>A: Add("alice")
    B->>B: Add("bob")
    A-->>B: merge ships {alice}
    B-->>A: merge ships {bob}
    Note over A,B: merge is set union
    Note over A,B: converged = {alice, bob}

Example

var seen = tree.GSet("campaign:autumn:reached");

// Two clusters add members concurrently; union keeps both.
await seen.AddAsync(Encoding.UTF8.GetBytes("alice"), cancellationToken);
await seen.AddAsync(Encoding.UTF8.GetBytes("bob"), cancellationToken);

bool reachedAlice = await seen.ContainsAsync(Encoding.UTF8.GetBytes("alice"), cancellationToken);
IReadOnlyList<byte[]> everyone = await seen.ToListAsync(cancellationToken);

See also: the add-wins OR-Set, the remove-wins RW-Set, and the CRDT overview.