Orleans and Aspire integration
Applies to: Orleans 8.0, Orleans 9.0, Orleans 10.0
Aspire provides a streamlined approach to building cloud-native applications with built-in support for Orleans. Starting with Orleans 8.0, you can use Aspire to orchestrate your Orleans cluster, manage backing resources (like Redis or Azure Storage), and automatically configure service discovery, observability, and health checks.
Overview
Section titled “Overview”Orleans integration with Aspire uses the Aspire.Hosting.Orleans package in your AppHost project. This package provides extension methods to:
- Define Orleans as a distributed resource
- Configure clustering providers (Redis, Azure Storage, ADO.NET)
- Configure grain storage providers
- Configure reminder providers
- Configure grain directory providers
- Model silo and client relationships
Prerequisites
Section titled “Prerequisites”Before using Orleans with Aspire, ensure you have:
- .NET 8.0 SDK or later
- Aspire CLI
- An IDE with Aspire support (Visual Studio 2022 17.9+, VS Code with C# Dev Kit, or JetBrains Rider)
Required packages
Section titled “Required packages”Your solution needs the following package references:
AppHost project
Section titled “AppHost project”<ItemGroup> <PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.3" /> <PackageReference Include="Aspire.Hosting.Orleans" Version="13.1.3" /> <PackageReference Include="Aspire.Hosting.Redis" Version="13.1.3" /></ItemGroup>Orleans silo project
Section titled “Orleans silo project”<ItemGroup> <PackageReference Include="Microsoft.Orleans.Server" Version="10.2.1" /> <PackageReference Include="Microsoft.Orleans.Clustering.Redis" Version="10.2.1" /> <PackageReference Include="Aspire.StackExchange.Redis" Version="13.4.6" /></ItemGroup>Orleans client project (if separate from silo)
Section titled “Orleans client project (if separate from silo)”<ItemGroup> <PackageReference Include="Microsoft.Orleans.Client" Version="10.2.1" /> <PackageReference Include="Microsoft.Orleans.Clustering.Redis" Version="10.2.1" /> <PackageReference Include="Aspire.StackExchange.Redis" Version="13.4.6" /></ItemGroup>Configure the AppHost
Section titled “Configure the AppHost”The AppHost project orchestrates your Orleans cluster and its dependencies.
Basic Orleans cluster with Redis clustering
Section titled “Basic Orleans cluster with Redis clustering”public static void BasicOrleansCluster(string[] args){ var builder = DistributedApplication.CreateBuilder(args);
// Add Redis for Orleans clustering var redis = builder.AddRedis("orleans-redis");
// Define the Orleans resource with Redis clustering var orleans = builder.AddOrleans("cluster") .WithClustering(redis);
// Add the Orleans silo project builder.AddProject<Projects.Silo>("silo") .WithReference(orleans) .WaitFor(redis) .WithReplicas(3);
builder.Build().Run();}Orleans with grain storage and reminders
Section titled “Orleans with grain storage and reminders”public static void OrleansWithStorageAndReminders(string[] args){ var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("orleans-redis");
var orleans = builder.AddOrleans("cluster") .WithClustering(redis) .WithGrainStorage("Default", redis) .WithGrainStorage("PubSubStore", redis) .WithReminders(redis);
builder.AddProject<Projects.Silo>("silo") .WithReference(orleans) .WaitFor(redis) .WithReplicas(3);
builder.Build().Run();}Separate silo and client projects
Section titled “Separate silo and client projects”When your Orleans client runs in a separate process (such as a web frontend), use the .AsClient() method:
public static void SeparateSiloAndClient(string[] args){ var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("orleans-redis");
var orleans = builder.AddOrleans("cluster") .WithClustering(redis) .WithGrainStorage("Default", redis);
// Backend Orleans silo cluster var silo = builder.AddProject<Projects.Silo>("backend") .WithReference(orleans) .WaitFor(redis) .WithReplicas(5);
// Frontend web project as Orleans client builder.AddProject<Projects.Client>("frontend") .WithReference(orleans.AsClient()) // Client-only reference .WaitFor(silo);
builder.Build().Run();}Configure the Orleans silo project
Section titled “Configure the Orleans silo project”In your Orleans silo project, configure Orleans to use the Aspire-provided resources:
public static void BasicSiloConfiguration(string[] args){ var builder = Host.CreateApplicationBuilder(args);
// Add Aspire service defaults (OpenTelemetry, health checks, etc.) builder.AddServiceDefaults();
// Add the Aspire Redis client for Orleans builder.AddKeyedRedisClient("orleans-redis");
// Configure Orleans - Aspire injects all configuration automatically builder.UseOrleans();
builder.Build().Run();}Configure with explicit connection string
Section titled “Configure with explicit connection string”If you need explicit control over the connection string, you can read it from configuration:
public static void ExplicitConnectionConfiguration(string[] args){ var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults(); builder.AddKeyedRedisClient("orleans-redis");
builder.UseOrleans(siloBuilder => { var redisConnectionString = builder.Configuration.GetConnectionString("orleans-redis");
siloBuilder.UseRedisClustering(options => { options.ConfigurationOptions = ConfigurationOptions.Parse(redisConnectionString!); });
siloBuilder.AddRedisGrainStorageAsDefault(options => { options.ConfigurationOptions = ConfigurationOptions.Parse(redisConnectionString!); }); });
builder.Build().Run();}Configure the Orleans client project
Section titled “Configure the Orleans client project”For separate client projects, configure the Orleans client similarly:
public static void BasicClientConfiguration(string[] args){ var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults(); builder.AddKeyedRedisClient("orleans-redis");
// Configure Orleans client - Aspire injects clustering configuration automatically builder.UseOrleansClient();
builder.Build().Run();}AppHost extension methods reference
Section titled “AppHost extension methods reference”The Aspire.Hosting.Orleans package provides these extension methods:
Core methods
Section titled “Core methods”| Method | Description |
|---|---|
builder.AddOrleans(name) | Adds an Orleans resource to the distributed application with the specified name. |
.WithClusterId(id) | Sets the Orleans ClusterId. Accepts a string or ParameterResource. If not specified, a unique ID is generated automatically. |
.WithServiceId(id) | Sets the Orleans ServiceId. Accepts a string or ParameterResource. If not specified, a unique ID is generated automatically. |
.AsClient() | Returns a client-only reference to the Orleans resource (doesn’t include silo capabilities). |
project.WithReference(orleans) | Adds the Orleans resource reference to a project, enabling configuration injection. |
Clustering
Section titled “Clustering”| Method | Description |
|---|---|
.WithClustering(resource) | Configures Orleans clustering to use the specified resource (Redis, Azure Storage, Cosmos DB, etc.). |
.WithDevelopmentClustering() | Configures in-memory, single-host clustering for local development only. Not suitable for production. |
Grain storage
Section titled “Grain storage”| Method | Description |
|---|---|
.WithGrainStorage(name, resource) | Configures a named grain storage provider using the specified resource. |
.WithMemoryGrainStorage(name) | Configures in-memory grain storage for the specified name. Data is lost on silo restart. |
Reminders
Section titled “Reminders”| Method | Description |
|---|---|
.WithReminders(resource) | Configures the Orleans reminder service using the specified resource. |
.WithMemoryReminders() | Configures in-memory reminders for development. Reminders are lost on silo restart. |
Streaming
Section titled “Streaming”| Method | Description |
|---|---|
.WithStreaming(name, resource) | Configures a named stream provider using the specified resource (e.g., Azure Queue Storage). |
.WithMemoryStreaming(name) | Configures in-memory streaming for development. |
.WithBroadcastChannel(name) | Configures a broadcast channel provider with the specified name. |
Grain directory
Section titled “Grain directory”| Method | Description |
|---|---|
.WithGrainDirectory(name, resource) | Configures a named grain directory using the specified resource. |
Service defaults pattern
Section titled “Service defaults pattern”Aspire uses a ServiceDefaults project pattern to share common configuration across all projects. For Orleans, this typically includes:
OpenTelemetry configuration
Section titled “OpenTelemetry configuration”public static IHostApplicationBuilder AddServiceDefaults( this IHostApplicationBuilder builder){ builder.ConfigureOpenTelemetry(); builder.AddDefaultHealthChecks();
return builder;}
public static IHostApplicationBuilder ConfigureOpenTelemetry( this IHostApplicationBuilder builder){ builder.Logging.AddOpenTelemetry(logging => { logging.IncludeFormattedMessage = true; logging.IncludeScopes = true; });
builder.Services.AddOpenTelemetry() .WithMetrics(metrics => { metrics.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddRuntimeInstrumentation() .AddMeter("Microsoft.Orleans"); // Orleans metrics }) .WithTracing(tracing => { tracing.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddSource("Microsoft.Orleans.Runtime") .AddSource("Microsoft.Orleans.Application"); });
return builder;}Azure Storage with Aspire
Section titled “Azure Storage with Aspire”You can use Azure Storage resources for Orleans clustering and persistence:
public static void AzureStorageWithAspire(string[] args){ var builder = DistributedApplication.CreateBuilder(args);
// Add Azure Storage for Orleans var storage = builder.AddAzureStorage("orleans-storage") .RunAsEmulator(); // Use Azurite emulator for local development
var tables = storage.AddTables("orleans-tables"); var blobs = storage.AddBlobs("orleans-blobs");
var orleans = builder.AddOrleans("cluster") .WithClustering(tables) .WithGrainStorage("Default", blobs) .WithReminders(tables);
builder.AddProject<Projects.Silo>("silo") .WithReference(orleans) .WaitFor(storage) .WithReplicas(3);
builder.Build().Run();}Development vs. production configuration
Section titled “Development vs. production configuration”Aspire makes it easy to switch between development and production configurations:
Local development (using emulators)
Section titled “Local development (using emulators)”public static void LocalDevelopment(string[] args){ var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("orleans-redis"); // Redis container runs automatically during development
var orleans = builder.AddOrleans("cluster") .WithClustering(redis);
// ...}Production (using managed services)
Section titled “Production (using managed services)”public static void ProductionConfig(string[] args){ var builder = DistributedApplication.CreateBuilder(args);
// Use existing Azure Cache for Redis var redis = builder.AddConnectionString("orleans-redis");
var orleans = builder.AddOrleans("cluster") .WithClustering(redis);
// ...}Health checks
Section titled “Health checks”Aspire automatically configures health check endpoints. You can add Orleans-specific health checks:
public static void ConfigureHealthChecks(IHostApplicationBuilder builder){ builder.Services.AddHealthChecks() .AddCheck<GrainHealthCheck>("orleans-grains") .AddCheck<SiloHealthCheck>("orleans-silo");}Best practices
Section titled “Best practices”-
Use ServiceDefaults: Share common configuration (OpenTelemetry, health checks) across all projects using a ServiceDefaults project.
-
Wait for dependencies: Always use
.WaitFor()to ensure backing resources (Redis, databases) are ready before Orleans silos start. -
Configure replicas: Use
.WithReplicas()to run multiple silo instances for fault tolerance and scalability. -
Separate client projects: For web frontends, use
.AsClient()to configure Orleans client-only mode. -
Use emulators for development: Aspire can run Redis, Azure Storage (Azurite), and other dependencies locally using containers.
-
Enable distributed tracing: Configure OpenTelemetry with Orleans source names to trace grain calls across the cluster.
See also
Section titled “See also”Applies to: Orleans 7.0
Aspire integration was introduced in Orleans 8.0. For Orleans 7.0, you can still deploy to Aspire-orchestrated environments, but the dedicated Aspire.Hosting.Orleans package and its extension methods are not available.
Consider upgrading to Orleans 8.0 or later to take advantage of the Aspire integration features.
Applies to: Orleans 3.x
Aspire integration is available in Orleans 8.0 and later. Orleans 3.x does not support Aspire.
