Table of Contents

Strongly Consistent Scans

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

What it shows

Lattice's scan primitives - CountAsync, ScanKeysAsync, and ScanEntriesAsync - are strongly consistent: no key is missed or double-counted because a shard split or rebalanced underneath the call, and a concurrent SetManyAtomicAsync is observed all-or-nothing. Each shard is read at its own moment, so a reading taken while ordinary writes land is exact shard by shard rather than one instant's image of the whole tree. For an add-only stream of writes like this sample's, that still makes every reading a count the tree genuinely held at some instant, and successive readings never go backwards. This sample seeds a baseline, hammers the tree with concurrent writes while repeatedly counting, and confirms the settled state is exact and duplicate-free.

Run it

dotnet run --project samples/StronglyConsistentScans

Expected output

Silo starting... ready.

Seeding 500 keys (item:0000 .. item:0499)...
  CountAsync()      = 500
  ScanKeysAsync -> 500 keys
  Agree on baseline: True

Adding 300 keys (extra:0000 .. extra:0299) concurrently while counting...
  All observed counts stayed within [500, 800]: True
  Observed counts were monotonic (never went backwards): True

Settled state after concurrent writes:
  CountAsync()             = 800
  Distinct keys from scan  = 800
  Exact and duplicate-free: True

Done: scans returned the exact live key set throughout concurrent writes.

When to use

  • Reporting or dashboards where an aggregate count must be exact rather than eventually consistent or best-effort.
  • Reconciliation and audit passes that must observe a consistent live key set while the tree keeps taking writes.
  • Any read path where a key missed or double-counted because a shard split mid-read, or an atomic batch seen half-applied, would be a correctness bug.

When not to use

  • If you need a stable, unchanging view across a long multi-page scan while writes continue, use a snapshot cursor instead (see SnapshotCursors). Strong consistency guarantees that a reading counts each key once, not that it is one instant's image of the whole tree while ordinary writes land, nor that two readings taken at different times return the same set.

Feature doc