Skip to content

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.

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

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)

Your solution needs the following package references:

<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>
<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>

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();
}
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();
}

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();
}

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();
}

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();
}

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();
}

The Aspire.Hosting.Orleans package provides these extension methods:

MethodDescription
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.
MethodDescription
.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.
MethodDescription
.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.
MethodDescription
.WithReminders(resource)Configures the Orleans reminder service using the specified resource.
.WithMemoryReminders()Configures in-memory reminders for development. Reminders are lost on silo restart.
MethodDescription
.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.
MethodDescription
.WithGrainDirectory(name, resource)Configures a named grain directory using the specified resource.

Aspire uses a ServiceDefaults project pattern to share common configuration across all projects. For Orleans, this typically includes:

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;
}

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();
}

Aspire makes it easy to switch between development and production configurations:

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);
// ...
}
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);
// ...
}

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");
}
  1. Use ServiceDefaults: Share common configuration (OpenTelemetry, health checks) across all projects using a ServiceDefaults project.

  2. Wait for dependencies: Always use .WaitFor() to ensure backing resources (Redis, databases) are ready before Orleans silos start.

  3. Configure replicas: Use .WithReplicas() to run multiple silo instances for fault tolerance and scalability.

  4. Separate client projects: For web frontends, use .AsClient() to configure Orleans client-only mode.

  5. Use emulators for development: Aspire can run Redis, Azure Storage (Azurite), and other dependencies locally using containers.

  6. Enable distributed tracing: Configure OpenTelemetry with Orleans source names to trace grain calls across the cluster.

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.