orleans
Provides guidance for building, testing, and deploying actor-based distributed systems with Orleans.
Install
mkdir -p .claude/skills/orleans && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/9558" && unzip -o skill.zip -d .claude/skills/orleans && rm skill.zipInstalls to .claude/skills/orleans
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Build or review distributed .NET applications with Orleans grains, silos, persistence, streaming, reminders, placement, transactions, serialization, event sourcing, testing, and cloud-native hosting.Key capabilities
- →Model grains
- →Configure silos
- →Implement persistence
- →Design streaming
How it works
Provides patterns and configuration for building distributed .NET applications with Orleans.
Inputs & outputs
When to use orleans
- →Modeling stateful entities like shopping carts
- →Implementing distributed transactions in grains
- →Testing grain behavior with test clusters
About this skill
Microsoft Orleans
Trigger On
- building or reviewing
.NETcode that usesMicrosoft.Orleans.*,Grain,IGrainWith*,UseOrleans,UseOrleansClient,IGrainFactory,JournaledGrain,ITransactionalState, or Orleans silo/client builders - testing Orleans code with
InProcessTestCluster,Aspire.Hosting.Testing,WebApplicationFactory, or shared AppHost fixtures - modeling high-cardinality stateful entities such as users, carts, devices, rooms, orders, digital twins, sessions, or collaborative documents
- choosing between grains, streams, broadcast channels, reminders, stateless workers, persistence providers, placement strategies, transactions, event sourcing, and external client/frontend topologies
- deploying or operating Orleans with Redis, Azure Storage, Cosmos DB, ADO.NET, .NET Aspire, Kubernetes, Azure Container Apps, or built-in/dashboard observability
- designing grain serialization contracts, versioning grain interfaces, configuring custom placement, or implementing grain call filters and interceptors
Workflow
-
Decide 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 string
-
Design coarse-grained async APIs. All grain interface methods must return
Task,Task<T>, orValueTask<T>. UseIAsyncEnumerable<T>for streaming responses. Avoid.Result,.Wait(), blocking I/O, lock-based coordination. UseTask.WhenAllfor 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)- Multiple named states per grain for different storage providers
JournaledGrain<TState, TEvent>for event-sourced grainsITransactionalState<TState>for ACID transactions across grainsGrain<TState>is legacy — use only when constrained by existing code
-
Pick the right runtime primitive deliberately:
- Standard grains for stateful request/response logic
[StatelessWorker]for pure stateless fan-out or compute helpers- Orleans streams for decoupled event flow and pub/sub with
[ImplicitStreamSubscription] - Broadcast channels for fire-and-forget fan-out with
[ImplicitChannelSubscription] RegisterGrainTimerfor activation-local periodic work (non-durable)- Reminders via
IRemindablefor durable low-frequency wakeups - Observers via
IGrainObserverandObserverManager<T>for one-way push notifications
-
Configure 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 types- Use surrogates (
IConverter<TOriginal, TSurrogate>) for types you don't own
-
Handle reentrancy and scheduling deliberately:
- Default is non-reentrant single-threaded execution (safe but deadlock-prone with circular calls)
[Reentrant]on grain class for full interleaving[AlwaysInterleave]on interface method for specific method interleaving[ReadOnly]for concurrent read-only methodsRequestContext.AllowCallChainReentrancy()for scoped reentrancy- Native
CancellationTokensupport (last parameter, optional default)
-
Choose hosting intentionally.
UseOrleansfor silos,UseOrleansClientfor separate clients- Co-hosted client runs in same process (reduced latency, no extra serialization)
- In Aspire, declare Orleans resource in AppHost, wire clustering/storage/reminders there, use
.AsClient()for frontend-only consumers - In Aspire-backed tests, resolve Orleans backing-resource connection strings from the distributed app and feed them into the test host instead of duplicating local settings
- Prefer
TokenCredentialwithDefaultAzureCredentialfor Azure-backed providers
-
Configure providers with production realism.
- In-memory storage, reminders, and stream providers are dev/test only
- Persistence: Redis, Azure Table/Blob, Cosmos DB, ADO.NET, DynamoDB
- Reminders: Azure Table, Redis, Cosmos DB, ADO.NET
- Clustering: Azure Table, Redis, Cosmos DB, ADO.NET, Consul, Kubernetes
- Streams: Azure Event Hubs, Azure Queue, Memory (dev only)
-
Treat placement as an optimization tool, not a default to cargo-cult.
ResourceOptimizedPlacementis default since 9.2 (CPU, memory, activation count weighted)RandomPlacement,PreferLocalPlacement,HashBasedPlacement,ActivationCountBasedPlacementSiloRoleBasedPlacementfor role-targeted placement- Custom placement via
IPlacementDirector+PlacementStrategy+PlacementAttribute - Placement filtering (9.0+) for zone-aware and hardware-affinity placement
- Activation repartitioning and rebalancing are experimental
-
Make the cluster observable.
- Standard
Microsoft.Extensions.Logging System.Diagnostics.Metricswith meter"Microsoft.Orleans"- OpenTelemetry export via
AddOtlpExporter+AddMeter("Microsoft.Orleans") - Distributed tracing via
AddActivityPropagation()with sources"Microsoft.Orleans.Runtime"and"Microsoft.Orleans.Application" - Orleans Dashboard for operational visibility (secure with ASP.NET Core auth)
- Health checks for cluster readiness
- Standard
-
Test the cluster behavior you actually depend on.
InProcessTestClusterfor new tests- Shared Aspire/AppHost fixtures for real HTTP, SignalR, SSE, or UI flows that must exercise the co-hosted Orleans topology
WebApplicationFactory<TEntryPoint>layered over a shared AppHost when tests need Host DI services,IGrainFactory, or direct grain/runtime access while keeping real infrastructure- Multi-silo coverage when placement, reminders, persistence, or failover matters
- Benchmark hot grains before claiming the design scales
- Use memory providers in test, real providers in integration tests
Architecture
flowchart 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"]
Deliver
- a justified Orleans fit, or a clear rejection when the problem should stay as plain
.NETcode - grain boundaries, grain identities, and activation behavior aligned to the domain model
- concrete choices for clustering, persistence, reminders, streams, placement, transactions, and hosting topology
- serialization contracts with
[GenerateSerializer],[Id], versioning via[Alias], and immutability annotations - an async-safe grain API surface with bounded state, proper reentrancy, and reduced hot-spot risk
- an explicit testing and observability plan for local development and production
- a test-harness choice that matches the assertion level: runtime-only, API/SignalR/UI, or direct Host DI/grain access
Validate
- Orleans is being used for many loosely coupled entities, not as a generic distributed hammer
- grain interfaces are coarse enough to avoid chatty cross-grain traffic
- no grain code blocks threads or mixes sync-over-async with runtime calls
- state is bounded, version-tolerant, and persisted only through intentional provider-backed writes
- all state and message types use
[GenerateSerializer]and[Id(N)]correctly - timers are not used where durable reminders are required; reminders are not used for high-frequency ticks
- in-memory storage, reminders, and stream providers are confined to dev/test usage
- Aspire projects register required keyed backing resources before
UseOrleans()orUseOrleansClient() - reentrancy is handled deliberately — circular call patterns use
[Reentrant],[AlwaysInterleave], orAllowCallChainReentrancy - transactional grains are marked
[Reentrant]and usePerformRead/PerformUpdate - hot grains, global coordinators, and affinity-heavy grains are measured and justified
- tests cover multi-silo behavior, persistence, and failover-sensitive logic when those behaviors matter
- Aspire-backed tests reuse one shared AppHost fixture and do not boot the distributed topology inside individual tests
- co-hosted Host tests do not start a redundant Orleans client unless external-client behavior is the thing under test
- Host or API
Content truncated.
When not to use it
- →Forcing Orleans onto shared-memory workloads
- →Blocking I/O
Prerequisites
Limitations
- →Avoid blocking I/O
- →Do not create unique grains per request
How it compares
Focuses on stateful, distributed entity modeling rather than generic .NET services.
Compared to similar skills
orleans side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| orleans (this skill) | 0 | 3mo | No flags | Advanced |
| dotnet-architect | 12 | 4mo | No flags | Advanced |
| dotnet-backend-patterns | 0 | 5mo | No flags | Advanced |
| messaging-decision | 0 | 1mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by managedcode
View all by managedcode →You might also like
dotnet-architect
sickn33
Expert .NET backend architect specializing in C#, ASP.NET Core, Entity Framework, Dapper, and enterprise application patterns. Masters async/await, dependency injection, caching strategies, and performance optimization. Use PROACTIVELY for .NET API development, code review, or architecture decisions.
dotnet-backend-patterns
brunolimaff-jpg
Master C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuratio...
messaging-decision
Brilhante29
Decide whether a portfolio repository should use no broker, transactional outbox, RabbitMQ, Kafka/Redpanda, Redis Streams, or NATS based on delivery semantics, ordering, replay, retry/DLQ, throughput, and benchmark evidence.
cqrs-implementation
wshobson
Implement Command Query Responsibility Segregation for scalable architectures. Use when separating read and write models, optimizing query performance, or building event-sourced systems.
database-design
davila7
Database design principles and decision-making. Schema design, indexing strategy, ORM selection, serverless databases.
database-schema-designer
davila7
Design robust, scalable database schemas for SQL and NoSQL databases. Provides normalization guidelines, indexing strategies, migration patterns, constraint design, and performance optimization. Ensures data integrity, query performance, and maintainable data models.