Skip to content

Client configuration

An external client runs outside a silo process and reaches the cluster through silo gateways. Install Microsoft.Orleans.Client, call UseOrleansClient, and configure the same cluster identity and clustering provider as the silos:

public static async Task RunExternalClient(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleansClient(clientBuilder =>
{
clientBuilder.Configure<ClusterOptions>(options =>
{
options.ServiceId = "orders";
options.ClusterId = "orders-production";
});
clientBuilder.UseRedisClustering(options =>
{
options.ConfigurationOptions =
ConfigurationOptions.Parse(
builder.Configuration.GetConnectionString("redis")!);
});
});
await builder.Build().RunAsync();
}

Client settings participate in the .NET options pattern. The host starts the Orleans client before later registered hosted services and stops it with the rest of the application. Resolve IClusterClient or IGrainFactory from .NET dependency injection; don’t build a second client singleton manually or create a new client per request.

For ASP.NET Core and other generic-host apps, keep a single client instance for the lifetime of the process. This is the same client you inject into controllers, background workers, hosted services, and other long-lived components. The host owns startup and shutdown; do not dispose the dependency-injected singleton or replace it with a static cache.

  • ServiceId identifies the logical Orleans application and should remain stable.
  • ClusterId identifies one deployment of that service. Use a different value to isolate environments or parallel deployments.
  • The client clustering provider discovers gateway-enabled silos. Its settings must point to the same membership data as the silos.

Common production clustering packages include Azure Table Storage, ADO.NET, Redis, Azure Cosmos DB, DynamoDB, Consul, and ZooKeeper. Static and localhost clustering are intended for development. Kubernetes hosting is a silo integration, not a client clustering provider.

When Aspire supplies the Orleans resource, register the corresponding keyed service client and use the parameterless form:

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

Orleans registers a default IClientConnectionRetryFilter. It retries eligible initial connection failures with linear backoff, up to 15 retries. Host startup fails if the client still can’t connect, the host is stopping, or the failure isn’t considered retryable.

Override the policy only when the application has different startup requirements:

public static void ConfigureClientRetry(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
var retryCount = 0;
builder.UseOrleansClient(clientBuilder =>
{
clientBuilder
.UseRedisClustering(options => { /* ... */ })
.UseConnectionRetryFilter(
async (exception, cancellationToken) =>
{
if (exception is not ConnectionFailedException ||
Interlocked.Increment(ref retryCount) > 5)
{
return false;
}
await Task.Delay(
TimeSpan.FromSeconds(5),
cancellationToken);
return true;
});
});
}

Bound every custom retry policy and honor the cancellation token so deployments can fail fast and shutdown isn’t delayed indefinitely.

Initial connection retries don’t make grain calls idempotent. A call can fail after the target started processing it, so retry application operations only when their semantics tolerate duplicates. Grain references remain usable after transient connectivity failures.

Configure gateway refresh and connection behavior through GatewayOptions or Orleans:Gateway. Orleans refreshes the gateway list from the clustering provider and reconnects as gateways become unavailable. Expose gateway endpoints only to client networks that require them; silo-to-silo traffic uses a separate endpoint.

For a co-hosted client, use UseOrleans instead. The silo’s client communicates directly with the cluster and doesn’t require a gateway hop.