Heterogeneous Orleans silos
Silos in one cluster can host different sets of grain classes. This lets you isolate workloads, use specialized hardware, or deploy grain implementations independently while retaining one Orleans cluster.

All silos and clients should reference the interfaces and serialization contracts they can exchange. A silo should reference only the grain implementation assemblies it can host.
Prefer assembly boundaries
Section titled “Prefer assembly boundaries”The simplest model is to put specialized grain classes in separate projects and reference each implementation project only from the silo host that should run it. Orleans discovers supported grain classes from generated type metadata.
For example:
- General-purpose silos reference
Orders.Grains. - GPU silos reference
Recommendations.Grains. - Clients reference
Orders.ContractsandRecommendations.Contracts, but neither implementation assembly.
The same grain implementation must be compatible across every silo that advertises support for that grain type.
Configuration
Section titled “Configuration”When one binary can run in several roles, configure Classes:
public static void ConfigureGrainTypes(ISiloBuilder siloBuilder){ siloBuilder.Configure<GrainTypeOptions>(options => { options.Classes.Clear(); options.Classes.Add(typeof(RecommendationGrain)); options.Classes.Add(typeof(ModelRegistryGrain)); });}Classes is a set of Type values. Use it to include the exact grain classes the process can host or remove discovered classes that a role must not host:
public static void ExcludeGrainType(ISiloBuilder siloBuilder){ siloBuilder.Configure<GrainTypeOptions>(options => { options.Classes.Remove(typeof(RecommendationGrain)); });}Don’t use obsolete grain-class exclusion option names from earlier Orleans versions.
Direct placement by capability
Section titled “Direct placement by capability”Use silo metadata and grain placement filtering when many silos load the same grain implementation but only some meet a placement requirement such as region, hardware, tenant, or reservation type.
Use heterogeneous grain type registration when a silo cannot host the implementation at all. Use placement filtering when it can host the type but placement should prefer or require metadata.
Deployment rules
Section titled “Deployment rules”- Keep ServiceId, ClusterId, clustering, and protocol configuration consistent across all roles.
- Deploy at least one healthy silo for every supported grain type before clients invoke it.
- Maintain capacity and redundancy independently for each specialized grain set.
- Roll out contract changes before implementations that require them.
- Avoid removing the last silo for a grain type while requests or durable work still target it.
Clients obtain cluster type information after connecting. Handle deployments so clients don’t depend on a grain type before supporting silos are available.
Limitations
Section titled “Limitations”- A request fails when no active silo supports its target grain type.
- Every silo that supports one grain type must use a compatible implementation and contract.
- Stateless worker grains should be consistently available across the cluster rather than split into incompatible heterogeneous sets.
- Implicit stream subscriptions require compatible grain availability; use explicit subscriptions when heterogeneous deployment makes ownership ambiguous.
Test topology changes with production-like role counts, especially the loss and replacement of the last silo supporting a type.
