---
title: "Release 2026-09-03 - Changelog"
url: "https://nsta1.github.io/Orleans.Lattice/changelog/2026-09-03.html"
source: "https://github.com/NSTA1/Orleans.Lattice/blob/release/9.9/CHANGELOG.md?plain=1#L1289-L1296"
documents: "Orleans.Lattice 9.9.0 (release line 9.9)"
built: "2026-10-04"
all-pages: "https://nsta1.github.io/Orleans.Lattice/llms.txt"
---
# Release 2026-09-03

Part of the [changelog](../CHANGELOG.md).

Single-package patch release: `Orleans.Lattice` advances to `9.5.1` and the rest of the family stays at `9.5.0`. This is a targeted hotfix cut from the `lattice-v9.5.0` tag rather than from `main`, so it carries exactly one change and none of the unreleased work queued behind it.

## Fixed

- **Every dot-based CRDT now keeps at most one dot per replica per slot, instead of growing without bound each time a slot is re-asserted.** Enabling an already-enabled flag, or re-adding an element already present, minted a fresh `OrSetDot` and appended it while nothing ever removed the dot it superseded, so a slot re-asserted N times carried N dots forever and every read, merge and serialisation of that one row paid O(N). N is unbounded in any workload that re-asserts on a schedule, which makes presence marking - a loop of `OrFlag(key).EnableAsync(...)` - the shape that reaches it first: a single presence row was observed growing until both reads and writes on its tree exceeded Orleans' 30 second response deadline, taking that tree out of service, and a unit probe retained 1,000 dots after 1,000 enables of one key. New shared machinery, `OrSetDotCompaction`, now collapses each slot to at most one dot per replica per side across `OrFlag`, `OrSet`, `RwFlag` and `RwSet`, so state is proportional to the number of replicas rather than to the number of assertions. The collapse is lossless only because a replica mints its own dots in counter order and cancellation is coverage-based - a cancelling dot from replica R at counter `t` cancels every dot from R at counter at or below `t`, rather than only the one it equals - so the two halves ship together and neither is sound alone. Convergence is unchanged: dots are never merged across replicas, so a concurrent assertion elsewhere keeps its own distinct dot and still wins or loses its primitive's tie-break exactly as before, which add-wins and remove-wins assert-versus-retract tests pin directly alongside commutativity, associativity and idempotence. No migration or operator step is needed, because `Compact()` runs on every mutation and every merge - including the delta fold used by replication and by write-ahead-log replay - so any key that is written or merged collapses its inherited history in place, and a key that is never re-asserted never bloated in the first place. `OrMap` is deliberately excluded, because its per-key entries carry a value rather than only a dot, so collapsing two entries from one replica would be silent data loss ([#1937](https://github.com/NSTA1/Orleans.Lattice/issues/1937)). ([#1938](https://github.com/NSTA1/Orleans.Lattice/pull/1938)) (`Orleans.Lattice` 9.5.1)

Newer release: [Release 2026-09-05: Fixed](../changelog/2026-09-05-2.md). Older release: [Release 2026-09-02](../changelog/2026-09-02.md). Contents: [Changelog](../CHANGELOG.md).
