Orleans grain directories
A grain directory maps a grain identity to the silo that currently hosts its activation. Orleans consults the directory when routing calls and coordinating single-activation grain placement.
Start with the default directory
Section titled “Start with the default directory”Orleans uses the built-in DistributedGrainDirectory by default. It keeps registrations in the cluster and coordinates partition ownership using versioned membership views. It requires no external service.
The directory coordinates registration and ownership transfer so that callers agree on an activation’s location as membership changes. Keep grain operations idempotent: failed calls and retries can still repeat application work.
To select LegacyGrainDirectory, call UseLegacyGrainDirectory on every silo.
For version upgrades, follow Grain directory migration.
Which grain directory should you use?
Section titled “Which grain directory should you use?”Use a pluggable directory for grain types that need different operational characteristics:
| Directory | Package | Consider it when |
|---|---|---|
| Redis | Microsoft.Orleans.GrainDirectory.Redis | A shared Redis service already meets latency and availability requirements. |
| Azure Table Storage | Microsoft.Orleans.GrainDirectory.AzureStorage | Azure Table is the preferred shared backing service. |
| Google Cloud Firestore | Microsoft.Orleans.GrainDirectory.Firestore | A shared Firestore database already meets latency and availability requirements. |
| ADO.NET | Microsoft.Orleans.GrainDirectory.AdoNet | Grain locations should use an existing supported relational database. |
| Custom | Application or third-party package | The application has a backend-specific requirement not met by built-in providers. |
External directories add network calls and another availability dependency. Apply them selectively and load-test activation-heavy workloads.
Configuration
Section titled “Configuration”Register the provider under a name and select it on the grain implementation:
public static void ConfigureNamedGrainDirectory( ISiloBuilder siloBuilder, ConfigurationOptions redisConfiguration){ siloBuilder.AddRedisGrainDirectory( "durable-directory", options => { options.ConfigurationOptions = redisConfiguration; });}[GrainDirectory("durable-directory")]public sealed class ShoppingCartGrain : Grain, IShoppingCartGrain{}Grain types without GrainDirectoryAttribute continue to use the default directory. You can register multiple named providers for different grain types.
To replace the default for all unannotated grain types, use the provider’s Use...GrainDirectoryAsDefault extension, for example UseRedisGrainDirectoryAsDefault, UseAzureTableGrainDirectoryAsDefault, or UseAdoNetGrainDirectoryAsDefault.
Named directories can also be configured under Orleans:GrainDirectory:{name} with an installed declarative provider:
{ "Orleans": { "GrainDirectory": { "durable-directory": { "ProviderType": "Redis", "ConnectionString": "redis.example.com:6380,ssl=true" } } }}Strongly-consistent in-cluster directory
Section titled “Strongly-consistent in-cluster directory”The default DistributedGrainDirectory is a strongly consistent in-cluster directory based on partitioned ranges and membership views. AddDistributedGrainDirectory selects it explicitly or registers an additional name for the same directory instance.
Configure default and named directory mappings consistently across the cluster. Multiple names share the same distributed directory instance.
The distributed directory defaults to one partition per silo (PartitionsPerSilo = 1). Change this only after testing with the expected cluster size and workload.
GetPartitionBoundaries configures the function which assigns starting hash boundaries to numbered partitions. The default uses the silo’s consistent hash for a single partition and cached uniform hashes in generation order for multiple partitions. A custom function returns an initialized ImmutableArray<T> containing exactly the configured number of boundaries, with each index identifying a partition. Keep each partition’s starting boundary stable throughout the silo’s membership and use equivalent functions on every silo. The immutable array shares its backing storage safely with directory membership snapshots.
If the boundary function throws or returns an invalid result, Orleans stops directory membership processing and reports an OrleansConfigurationException to membership readers and refresh calls. Correct the boundary configuration and restart the affected silos.
The partition count and boundary function are captured when the directory is created. Keep both consistent across the cluster.
Operational guidance
Section titled “Operational guidance”- Keep directory backend latency low; activation and first-call latency depend on it.
- Provision external directories for the aggregate cluster workload and failure bursts.
- Don’t use the grain directory as application state storage.
- Keep grain activation and deactivation idempotent.
- Test silo loss, rolling upgrades, and full-cluster restarts.
- Monitor duplicate-activation, directory, membership, and provider errors.
For architectural background, see Grain directory implementation.
