Samples
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 samples.md, and llms.txt lists every page.Each sample lives in its own directory under samples/; nearly all are self-contained runnable projects, and the exceptions are called out below.
Feature gallery
Minimal, focused samples, grouped by the same concerns as the feature catalogue. Most are independent console apps that host a single-silo in-process cluster (like HelloWorld), demonstrate one capability with heavily-commented, before/after output, and carry their own README, most with a "When to use / When not to use" note; run those with dotnet run --project samples/<Name>. The exceptions say so in their row - notably the two-cluster CrossClusterReplication, CrossClusterAuthorization and Explorer samples, the Azure-deployed ClusterScaling, the containerised RepoContextContainer, and AgentBacklog, a tool-driven walkthrough with no project of its own.
Four samples have a detailed section of their own further down: HelloWorld, the minimal starting point, and MultiSiteManufacturing, VehicleFleetSimulator, and ClusterScaling, which deploy or compose more than one process.
Core Storage and Durability
| Sample | What it shows |
|---|---|
| AtomicWrites | SetManyAtomicAsync all-or-nothing multi-key writes, a failed-guard batch that leaves no partial state, and the cross-tree IGrainFactory overload. |
| AtomicAction | IAtomicActionGrain saga / TCC coordinator running a Lattice tree write and a custom external effect in one all-or-nothing transaction: a committing plan, a rolling-back plan that restores the tree pre-image and releases the external effect, and an idempotent retry. |
| DistributedLock | ILatticeLockGrain FIFO-fair cluster-wide lock / lease: acquire / renew / release with monotonic fencing tokens, non-blocking try-acquire under contention, and a queued waiter granted the instant the holder releases. |
| ConflictFreeMerges | Two CRDT writers converging to the same result regardless of merge order. |
| StronglyConsistentScans | CountAsync / ScanKeysAsync / ScanEntriesAsync missing and double-counting no key while concurrent writes land (each shard is read at its own moment), and returning the exact live key set once they settle. |
| PredicateOperations | Server-side Expression<Func<T, bool>> push-down so only matching keys or values cross the wire. |
| DurableCursors | A server-checkpointed cursor resuming from its last yielded key after a client restart. |
| SnapshotCursors | Strict snapshot isolation: mid-iteration writes stay invisible to an open snapshot cursor. |
| Snapshots | An offline point-in-time copy of a tree into an independent destination tree. |
| BulkLoading | Seeding an empty tree via one-shot BulkLoadAsync and streaming IAsyncEnumerable ingestion. |
| OnlineReshard | Growing the physical shard count online with reads, writes, and data intact throughout. |
| Resize | Changing MaxLeafKeys / MaxInternalChildren on a live, populated tree. |
| Ttl | Per-entry time-to-live: a key visible before its TTL and gone after it expires. |
| SoftDeleteRecovery | Soft-deleting a tree within its retention window, recovering it, then purging permanently. |
| TreeRegistry | Enumerating all user trees and their per-tree configuration overrides. |
| RetryPolicy | An idempotency-keyed retry policy recovering from simulated transient storage faults. |
Replication and Distribution
| Sample | What it shows |
|---|---|
| CrossClusterReplication | Two in-process clusters over gRPC where a write on one converges onto the other. |
| RuntimeReplicationConfig | Enabling cross-cluster replication for a tree at runtime through the replication control API, instead of declaring replicated trees statically at boot. |
Governance
| Sample | What it shows |
|---|---|
| SchemaEnforcement | The two opt-in Orleans.Lattice.Schema capabilities over the opaque-byte[] core: per-tree write validation (a malformed write rejected with LatticeSchemaViolationException and never persisted), and self-describing value versioning with read-time upcasting. |
| MultiTenancy | A single-silo tour of multi-tenancy: the tenant registry, the isolation naming seam, and the operator control-plane facade. |
| InstallableApps | A single-silo tour of the installable App concept through the ILatticeAppsControl facade: an embedded manifest, a version-pinned operator consent binding the app's role to a membership group, app-owned authorization rules compiled on enable, and an uninstall that soft-deletes the app tree - with a direct edit of an app-owned rule refused (LatticeAppOwnedRuleException) and narrowed consent failing activation closed. |
Identity and Security
| Sample | What it shows |
|---|---|
| Authorization | Single-silo default-deny authorization with group and nested-group membership: a group nested inside another group, per-tree/prefix/key rules, read-visibility range pruning, and a runtime grant via nesting. |
| EntraAuthorization | Single-silo authorization driven by a real Microsoft Entra ID identity: the signed-in Azure CLI user's oid is the tree owner (sole bootstrap administrator), so the owner writes and reads a value while an anonymous request is denied by the default-deny gate. |
| PasswordProtection | A username/password front door for the State API gRPC surface (AddEnvVarCredentialAuthorizer) composed with per-tree authorization: a bootstrap admin plus a read-only user, wrong-password and anonymous calls rejected, and one tree hidden from the reader. |
| CrossClusterAuthorization | Two in-process clusters where the reserved membership and authorization-policy system trees converge over gRPC replication, so a grant or revoke authored on one site becomes enforced on the other. |
Administration and Operations
Operations
| Sample | What it shows |
|---|---|
| BackupAndRestore | The Orleans.Lattice.Backup surface end to end against a single in-process silo, using the default in-cluster backup sink. |
| ClusterScaling | A deployable Azure Container Apps multi-silo cluster whose replica count is autoscaled by the Orleans.Lattice.Scaling compute-axis signal through a KEDA metrics-api rule, with a bundled load driver. Deploy-to-Azure, not in-process. |
| Diagnostics | The DiagnoseAsync per-tree health snapshot: shard depth, live keys, tombstones, hotness. |
| Events | Subscribing to the per-tree LatticeTreeEvent Orleans stream. |
| Metrics | Reading the orleans.lattice meter instruments with a MeterListener. |
| StateExplorer | A console tree-explorer over the read-only state-API gRPC surface from Orleans.Lattice.Api.State. |
Explorer console (in progress)
Status: in progress. The Explorer is under active development, so this sample tracks a surface that is still moving.
| Sample | What it shows |
|---|---|
| Explorer | The opt-in Orleans.Lattice.Explorer.Web hosting library co-hosted in one process with a two-region estate - two single-silo clusters with tenancy on, replication between them, and one shared backup sink - so every Explorer area can be browsed against live data; --minimal runs a single region with no tenancy and no peer. In progress - the Explorer surface is still moving. |
AI and MCP
| Sample | What it shows |
|---|---|
| McpServer | A single-silo cluster co-hosted with the Model Context Protocol endpoint from Orleans.Lattice.Api.Mcp, exposing the API facades as agent-callable tools. |
| McpTelemetry | A single-silo cluster co-hosted with the Orleans.Lattice.Api.Mcp.Telemetry add-on, exposing cluster metrics to an agent over a read-only Prometheus-backed proxy. Start the bundled Prometheus with Docker Compose before running it. |
| RepoContextContainer | The RepoContext MCP server run as a single restart-durable container alongside its embedding companion. |
| AgentBacklog | A tool-driven walkthrough, run against the RepoContextContainer host, of the claim, lease, fencing, and release surface that makes an agent-operated backlog safe for several agents to drain at once, plus a copyable backlog template. |
Indexing, Search and Views
| Sample | What it shows |
|---|---|
| MaterialisedViews | A filter view and a sum-aggregation view maintained off the source tree's WAL. |
| HistoryViews | An opt-in durable per-key history view whose revisions survive WAL garbage collection. |
| ChangeHistory | Reading a key's revision timeline with ScanEntryHistoryAsync. |
| TagIndexes | Tagging keys and querying them back with WithAllTags (intersection) and WithAnyTags (union). |
| GrainIndex | Indexing a grain's typed state and running typed predicate queries over it, including a two-property conjunction and a de-duplicated disjunction. |
| VectorSearch | Approximate nearest-neighbour search with the in-memory index core of Orleans.Lattice.Vector, run with no silo: sub-linear query cost, honest per-query reporting of the path that answered, recall measured against an exact oracle, and first-class deletes. |
Reliability and Formal Verification
| Sample | What it shows |
|---|---|
| VerifiedAtomicCommit | A concurrent snapshot reader (GetManyAsync) races a flipping atomic saga and never observes a torn view - the all-or-nothing property the atomic-commit cores, Coyote models, and TLA+ spec machine-check. |
| VerifiedWalDurability | The two WAL cursor-registry properties that stop the garbage collector trimming an entry a consumer has not acked - per-consumer monotonicity and the min-cursor trim floor - driven on the production registry with no silo. These are the properties the WAL cores and their Coyote models machine-check. |
HelloWorld
Minimal interactive REPL over a single-silo, in-memory Orleans cluster. Starts a silo configured with AddLattice(...) + in-memory grain storage and reminders, then prompts for commands - create, read, update, delete, list, exit - and applies each one against a tree named hello-world. Every operation is timed with Stopwatch and reported as [OK] / [FAIL] with the elapsed milliseconds, so it doubles as a quick sanity check that a local build of Orleans.Lattice behaves correctly (the sample references the library project directly).
Run it with:
dotnet run --project samples/HelloWorld
MultiSiteManufacturing
samples/MultiSiteManufacturing
Regulated process-engineering traceability demo built on Blazor Server + gRPC + Orleans + Orleans.Lattice, backed by Azure Table Storage and Azure Storage Queues (Azurite for local development). Models a turbine-blade lifecycle (forge -> heat-treat -> machining -> NDT -> MRB -> FAI) across seven process sites, with a bulk-loaded inventory, operator-driven fact emission, a chaos fly-out for fault injection (site pause, delay and reorder, per-backend storage faults, a simulated intra-cluster partition, and a cross-cluster replication pause), and a live divergence feed comparing a baseline LWW backend against the Orleans.Lattice fact store.
The sample runs as two independent Orleans clusters (us and eu), each with two silos, connected by an opt-in cross-cluster replication link over gRPC so changes in one cluster converge on the other.
Supporting documentation lives alongside the sample:
README.md- overview, run instructions, and feature tour.approach.md- implementation rationale, gotchas, and the reasoning behind each design choice.architecture.md- structural view: topology, component graph, grain interdependencies, Lattice trees, replication sequence.glossary.md- domain and implementation terms.
Run it with:
./samples/MultiSiteManufacturing/run.ps1
The script builds the host image if needed, starts both clusters (four silos, one Azurite per cluster plus a shared azurite-backup account, two Traefik proxies, and a Prometheus + Grafana pair) under Docker Compose, and prints the per-cluster URLs - http://localhost:5001 for us and http://localhost:5002 for eu. Use -Down to tear everything back down, -Clean to wipe state between runs, and -Logs to tail silo logs (-Service narrows -Logs to one compose service). -Username / -Password bring the stack up with state-API authentication, -Backup enables the backup and restore subsystem, and -NoBuild reuses the cached host image.
VehicleFleetSimulator
A simulated vehicle fleet that streams structured telemetry events over gRPC. It is the load generator behind the docker-compose benchmark scenarios and the real-Azure throughput harness, both of which build on its projects (see Benchmarks), and the foundation for a future sample that bridges the simulator's event stream into a Lattice tree. The simulator itself does not depend on the lattice library - it builds and runs on its own, with its own VehicleFleetSimulator.slnx.
The full stack (Azurite + Silo + gRPC API + Blazor WASM UI) runs under Docker Compose:
./samples/VehicleFleetSimulator/run.ps1
UI on http://localhost:8090, API on http://localhost:8080. See samples/VehicleFleetSimulator/README.md for the full project layout, the on-import test-parallelism fix, and the planned Lattice-bridge sample.
ClusterScaling
A deployable Azure Container Apps (ACA) sample that proves the Orleans.Lattice.Scaling autoscaling signal drives KEDA replica scale-out on the compute axis. One container image runs as a genuine multi-silo Orleans cluster: each replica joins over real Azure Storage clustering and persists grain state and the Lattice write-ahead log to Azure Table storage, all via managed identity (no connection strings). Each replica co-hosts the write-capable gRPC data API - gated by a hashed admin password injected as an ACA secret and presented as HTTP Basic over ACA's managed TLS ingress - and the /lattice/scale HTTP signal endpoint the ACA KEDA metrics-api scale rule scrapes.
A bundled .NET LoadDriver console drives the compute axis (activation and dispatch pressure, not storage growth) so the cluster's scaleValue rises and ACA scales the replica count out. The deploy/ folder provisions everything from two bicep templates - main.bicep for the cluster and registry.bicep for the Basic container registry that deploy.ps1 builds the silo image into - plus PowerShell scripts:
./samples/ClusterScaling/deploy/deploy.ps1 # provision + deploy
./samples/ClusterScaling/deploy/drive-load.ps1 # run the load driver, watch replicas grow
./samples/ClusterScaling/deploy/teardown.ps1 # delete the resource group
See samples/ClusterScaling/README.md for the full walkthrough, the two-axis note, and the prerequisites. Documentation for the underlying signal lives under docs/lattice.scaling.