Table of Contents

Min-Register (Monotone Low-Water Mark)

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 minregister.md, and llms.txt lists every page.

tree.MinRegister<T>(key, orderKeySelector) -> MinRegisterAccessor<T>, merge mode LatticeMergeMode.MinRegister.

Semantics

A Min-Register is the mirror image of the Max-Register: it keeps the smallest totally-ordered value ever written - a monotone low-water mark. A write advances the register only when the candidate beats the current value under the total order; concurrent active-active writes from different clusters converge on the single smallest value because the fold is a directional min over the total order, which is commutative, associative, and idempotent.

As with the Max-Register, you supply an orderKeySelector that produces an order-preserving byte[] key for a value - its unsigned lexicographic byte order must match the intended value order. The key travels on the wire alongside the value so the receiver folds without needing your comparer.

Reach for it when a value only ever moves down: a min-seen latency floor, a first-seen timestamp, a lowest-price watermark. Its mirror is the Max-Register; for keeping concurrent values rather than the extreme, use the MV-Register.

Behaviour

Two concurrent Min-Register writes converging on the smaller. An order diagram drawn as a chain. A Min-Register orders values downward, so a smaller value sits higher. At the bottom the register is unset. Cluster A writes 42, one step up the chain. Cluster B, at the same time, writes 37, which is smaller and so sits above 42. Merging keeps the smaller value, so A rises to 37 and B stays there.

Both clusters hold 37. Under the min order the smaller value is the higher state, so the join is the smaller write itself.

The fold keeps the smaller value under the total order, so it is commutative, associative, and idempotent.

sequenceDiagram
    participant A as Cluster A
    participant B as Cluster B
    A->>A: Set(42)
    B->>B: Set(37)
    A-->>B: merge ships candidate 42
    B-->>A: merge ships candidate 37
    Note over A,B: fold keeps the smaller under the total order
    Note over A,B: converged = 37 (min-wins)

Example

// The order key must be order-preserving: big-endian bytes of a non-negative reading.
var floor = tree.MinRegister<long>("service:api:latency-floor-ms", static v =>
{
    var key = new byte[8];
    System.Buffers.Binary.BinaryPrimitives.WriteInt64BigEndian(key, v);
    return key;
});

// Two clusters report latencies concurrently; the register keeps the smaller.
await floor.SetAsync(42, cancellationToken);
await floor.SetAsync(37, cancellationToken);

long lowest = await floor.GetAsync(cancellationToken); // 37

// Before the first write GetAsync returns default(T) - 0 for a long - so ask
// HasValueAsync when "never written" must be told apart from a real 0.
bool written = await floor.HasValueAsync(cancellationToken);

See also: its high-water mirror Max-Register, the multi-value MV-Register, and the CRDT overview.