GSet
A set that only grows. Elements can be added but never removed. Merging two GSets is just set union.
Converges to: the union of all elements ever added across all replicas.
Merge rule
piece(a, b) is a.elements ∪ b.elements. Set union is idempotent (re-adding something doesn't change the result), commutative, and associative — the three laws that guarantee convergence.
Code examples
Add and merge:
@Test
fun addProducesADeltaThatAddsAnElement() {
val empty = GSet.empty<String>()
val delta = empty.add("x")
val next = empty.piece(delta)
assertTrue(next.contains("x"))
assertEquals(setOf("x"), next.elements)
}
@Test
fun mergeIsUnion() {
val left = GSet.of("x", "y")
val right = GSet.of("y", "z")
assertEquals(setOf("x", "y", "z"), left.piece(right).elements)
}
When to use
GSet is the right choice when elements are only ever added — completed tasks, acknowledged events, registered participants. For a set where elements can be removed, see ORSet (observe-remove, add-wins on conflict) or TwoPhaseSet (remove-wins, permanent tombstone).
Last modified: 22 June 2026