ワンクリックで
dotnet-orleans
// Build or review distributed .NET applications with Orleans grains, silos, persistence, streaming, reminders, placement, transactions, serialization, event sourcing, testing, and cloud-native hosting.
// Build or review distributed .NET applications with Orleans grains, silos, persistence, streaming, reminders, placement, transactions, serialization, event sourcing, testing, and cloud-native hosting.
Build, upgrade, and operate .NET Aspire application hosts with current CLI, AppHost, ServiceDefaults, integrations, dashboard, testing, and Azure deployment patterns for distributed apps.
Integrate ManagedCode.Orleans.Graph into an Orleans-based .NET application for graph-oriented relationships, edge management, and traversal logic on top of Orleans grains. Use when the application models graph structures in a distributed Orleans system.
Use ManagedCode.Orleans.SignalR when a distributed .NET application needs Orleans-based coordination of SignalR real-time messaging, hub delivery, and grain-driven push flows.
Implement or review SignalR hubs, streaming, reconnection, transport, and real-time delivery patterns in ASP.NET Core applications.
Build long-running .NET background services with `BackgroundService`, Generic Host, graceful shutdown, configuration, logging, and deployment patterns suited to workers and daemons.
| name | dotnet-orleans |
| description | Build or review distributed .NET applications with Orleans grains, silos, persistence, streaming, reminders, placement, transactions, serialization, event sourcing, testing, and cloud-native hosting. |
| compatibility | Prefer current Orleans releases (10.x / 9.x) with `UseOrleans`, `IPersistentState<TState>`, `RegisterGrainTimer`, `[GenerateSerializer]`, modern providers, and production-grade clustering. |
.NET code that uses Microsoft.Orleans.*, Grain, IGrainWith*, UseOrleans, UseOrleansClient, IGrainFactory, JournaledGrain, ITransactionalState, or Orleans silo/client buildersInProcessTestCluster, Aspire.Hosting.Testing, WebApplicationFactory, or shared AppHost fixturesDecide whether Orleans fits. Use it when the system has many loosely coupled interactive entities that can each stay small and single-threaded. Do not force Orleans onto shared-memory workloads, long batch jobs, or systems dominated by constant global coordination.
Model grain boundaries around business identity. Prefer one grain per user, cart, device, room, order, or other durable entity. Never create unique grains per request — use [StatelessWorker] for stateless fan-out. Grain identity types:
IGrainWithGuidKey — globally unique entitiesIGrainWithIntegerKey — relational DB integrationIGrainWithStringKey — flexible string keysIGrainWithGuidCompoundKey / IGrainWithIntegerCompoundKey — composite identity with extension stringDesign coarse-grained async APIs. All grain interface methods must return Task, Task<T>, or ValueTask<T>. Use IAsyncEnumerable<T> for streaming responses. Avoid .Result, .Wait(), blocking I/O, lock-based coordination. Use Task.WhenAll for parallel cross-grain calls. Apply [ResponseTimeout("00:00:05")] on interface methods when needed.
Choose the right state pattern:
IPersistentState<TState> with [PersistentState("name", "provider")] for named persistent state (preferred)JournaledGrain<TState, TEvent> for event-sourced grainsITransactionalState<TState> for ACID transactions across grainsGrain<TState> is legacy — use only when constrained by existing codePick the right runtime primitive deliberately:
[StatelessWorker] for pure stateless fan-out or compute helpers[ImplicitStreamSubscription][ImplicitChannelSubscription]RegisterGrainTimer for activation-local periodic work (non-durable)IRemindable for durable low-frequency wakeupsIGrainObserver and ObserverManager<T> for one-way push notificationsConfigure serialization correctly:
[GenerateSerializer] on all state and message types[Id(N)] on each serialized member for stable identification[Alias("name")] for safe type renaming[Immutable] to skip copy overhead on immutable typesIConverter<TOriginal, TSurrogate>) for types you don't ownHandle reentrancy and scheduling deliberately:
[Reentrant] on grain class for full interleaving[AlwaysInterleave] on interface method for specific method interleaving[ReadOnly] for concurrent read-only methodsRequestContext.AllowCallChainReentrancy() for scoped reentrancyCancellationToken support (last parameter, optional default)Choose hosting intentionally.
UseOrleans for silos, UseOrleansClient for separate clients.AsClient() for frontend-only consumersTokenCredential with DefaultAzureCredential for Azure-backed providersConfigure providers with production realism.
Treat placement as an optimization tool, not a default to cargo-cult.
ResourceOptimizedPlacement is default since 9.2 (CPU, memory, activation count weighted)RandomPlacement, PreferLocalPlacement, HashBasedPlacement, ActivationCountBasedPlacementSiloRoleBasedPlacement for role-targeted placementIPlacementDirector + PlacementStrategy + PlacementAttributeMake the cluster observable.
Microsoft.Extensions.LoggingSystem.Diagnostics.Metrics with meter "Microsoft.Orleans"AddOtlpExporter + AddMeter("Microsoft.Orleans")AddActivityPropagation() with sources "Microsoft.Orleans.Runtime" and "Microsoft.Orleans.Application"Test the cluster behavior you actually depend on.
InProcessTestCluster for new testsWebApplicationFactory<TEntryPoint> layered over a shared AppHost when tests need Host DI services, IGrainFactory, or direct grain/runtime access while keeping real infrastructureflowchart LR
A["Distributed requirement"] --> B{"Many independent<br/>interactive entities?"}
B -->|No| C["Plain service / worker / ASP.NET Core"]
B -->|Yes| D["Model one grain per business identity"]
D --> E{"State pattern?"}
E -->|"Persistent"| F["IPersistentState<T>"]
E -->|"Event-sourced"| F2["JournaledGrain<S,E>"]
E -->|"Transactional"| F3["ITransactionalState<T>"]
E -->|"In-memory only"| G["Activation state"]
D --> H{"Communication?"}
H -->|"Pub/sub"| I["Orleans streams"]
H -->|"Broadcast"| I2["Broadcast channels"]
H -->|"Push to client"| I3["Observers"]
H -->|"Request/response"| I4["Direct grain calls"]
D --> J{"Periodic work?"}
J -->|"Activation-local"| K["RegisterGrainTimer"]
J -->|"Durable wakeups"| L["Reminders"]
D --> M{"Client topology?"}
M -->|"Separate process"| N["UseOrleansClient / .AsClient()"]
M -->|"Same process"| O["Co-hosted silo+client"]
F & F2 & F3 & G & I & I2 & I3 & I4 & K & L & N & O --> P["Serialization → Placement → Observability → Testing → Deploy"]
.NET code[GenerateSerializer], [Id], versioning via [Alias], and immutability annotations[GenerateSerializer] and [Id(N)] correctlyUseOrleans() or UseOrleansClient()[Reentrant], [AlwaysInterleave], or AllowCallChainReentrancy[Reentrant] and use PerformRead/PerformUpdateOpen only what you need. Each reference is topic-focused for token economy:
InProcessTestCluster, shared AppHost fixtures, WebApplicationFactory, SignalR, and PlaywrightOfficial sources: