Silo Configuration
Complete siloConfig CE reference.
Silo Configuration
Section titled “Silo Configuration”Complete guide to the siloConfig { } computation expression.
What you’ll learn
Section titled “What you’ll learn”- How to configure clustering, storage, streaming, and reminders
- TLS/mTLS for secure silo communication
- Dashboard, health checks, and startup tasks
- Grain versioning, collection age, and endpoints
- Call filters and grain services
Overview
Section titled “Overview”The siloConfig { } CE builds a SiloConfig record. Apply it to a host with SiloConfig.applyToHost:
open Orleans.FSharp.Runtime
let config = siloConfig { useLocalhostClustering addMemoryStorage "Default"}
let builder = HostApplicationBuilder()SiloConfig.applyToHost config builderlet host = builder.Build()host.Run()Or apply directly to an ISiloBuilder with SiloConfig.applyToSiloBuilder.
Clustering
Section titled “Clustering”Localhost (development)
Section titled “Localhost (development)”siloConfig { useLocalhostClustering }Requires Microsoft.Orleans.Clustering.Redis.
let connStr = Environment.GetEnvironmentVariable("REDIS_CONNECTION")
siloConfig { addRedisClustering connStr addMemoryStorage "Default"}Azure Table
Section titled “Azure Table”Requires Microsoft.Orleans.Clustering.AzureStorage.
let connStr = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION")
siloConfig { addAzureTableClustering connStr addMemoryStorage "Default"}ADO.NET (PostgreSQL, SQL Server)
Section titled “ADO.NET (PostgreSQL, SQL Server)”Requires Microsoft.Orleans.Clustering.AdoNet.
let connStr = Environment.GetEnvironmentVariable("POSTGRES_CONNECTION")
siloConfig { addAdoNetClustering connStr "Npgsql" addMemoryStorage "Default"}The second argument is the ADO.NET provider invariant. Common values: "Npgsql" (PostgreSQL), "System.Data.SqlClient" (SQL Server), "MySql.Data.MySqlClient" (MySQL).
Kubernetes
Section titled “Kubernetes”Use the Kubernetes module for automatic discovery via the Kubernetes API:
open Orleans.FSharp.Kubernetes
siloConfig { // Use CustomClustering to wire Kubernetes hosting addCustomStorage "Default" (fun sb -> sb)}
// Apply Kubernetes clustering separately on the ISiloBuilderKubernetes.useKubernetesClustering siloBuilder |> ignoreRequires Microsoft.Orleans.Hosting.Kubernetes.
Storage Providers
Section titled “Storage Providers”In-memory
Section titled “In-memory”Data is lost on silo restart. Good for development and testing.
siloConfig { addMemoryStorage "Default" }Requires Microsoft.Orleans.Persistence.Redis.
let connStr = Environment.GetEnvironmentVariable("REDIS_CONNECTION")
siloConfig { addRedisStorage "Default" connStr }Azure Blob
Section titled “Azure Blob”Requires Microsoft.Orleans.Persistence.AzureStorage.
let connStr = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION")
siloConfig { addAzureBlobStorage "Default" connStr }Azure Table
Section titled “Azure Table”Requires Microsoft.Orleans.Persistence.AzureStorage.
siloConfig { addAzureTableStorage "Default" connStr }ADO.NET
Section titled “ADO.NET”Requires Microsoft.Orleans.Persistence.AdoNet.
siloConfig { addAdoNetStorage "Default" connStr "Npgsql" }Cosmos DB
Section titled “Cosmos DB”Requires Microsoft.Orleans.Persistence.Cosmos.
let endpoint = Environment.GetEnvironmentVariable("COSMOS_ENDPOINT")
siloConfig { addCosmosStorage "Default" endpoint "MyDatabase" }DynamoDB
Section titled “DynamoDB”Requires Microsoft.Orleans.Persistence.DynamoDB.
siloConfig { addDynamoDbStorage "Default" "us-east-1" }Custom
Section titled “Custom”For any storage provider not covered above:
siloConfig { addCustomStorage "MyStore" (fun siloBuilder -> siloBuilder.AddMyCustomStorage("MyStore") )}Multiple providers
Section titled “Multiple providers”You can register multiple storage providers with different names:
siloConfig { useLocalhostClustering addMemoryStorage "Default" addRedisStorage "Cache" redisConnStr addAzureBlobStorage "Archive" azureConnStr}Then reference each by name in your grain definitions:
grain { persist "Cache" ... }grain { persist "Archive" ... }Streaming
Section titled “Streaming”In-memory streams
Section titled “In-memory streams”siloConfig { useLocalhostClustering addMemoryStorage "Default" addMemoryStreams "StreamProvider"}A PubSubStore memory storage is automatically added if not already configured.
Persistent streams
Section titled “Persistent streams”For durable streams backed by queues (Event Hubs, Redis, etc.):
siloConfig { addPersistentStreams "MyStreams" adapterFactory configurator}Event Hubs
Section titled “Event Hubs”Use the StreamProviders module:
open Orleans.FSharp.StreamProviders
let connStr = Environment.GetEnvironmentVariable("EVENTHUB_CONNECTION")let configureFn = StreamProviders.addEventHubStreams "EventHubProvider" connStr "my-hub"
// Apply to siloBuilder directlyconfigureFn siloBuilder |> ignoreAzure Queue
Section titled “Azure Queue”let configureFn = StreamProviders.addAzureQueueStreams "QueueProvider" azureConnStrconfigureFn siloBuilder |> ignoreBroadcast channels
Section titled “Broadcast channels”Broadcast channels deliver messages to ALL subscriber grains (fan-out):
siloConfig { addBroadcastChannel "Notifications"}Reminders
Section titled “Reminders”In-memory (development)
Section titled “In-memory (development)”siloConfig { addMemoryReminderService }Requires Microsoft.Orleans.Reminders.Redis.
siloConfig { addRedisReminderService connStr }Custom
Section titled “Custom”siloConfig { addCustomReminderService (fun siloBuilder -> siloBuilder.UseMyReminderService() )}TLS / mTLS
Section titled “TLS / mTLS”TLS by subject name
Section titled “TLS by subject name”Requires Microsoft.Orleans.Connections.Security.
siloConfig { useLocalhostClustering useTls "CN=my-silo-cert"}TLS with certificate instance
Section titled “TLS with certificate instance”let cert = new X509Certificate2("path/to/cert.pfx", "password")
siloConfig { useLocalhostClustering useTlsWithCertificate cert}Mutual TLS (mTLS)
Section titled “Mutual TLS (mTLS)”siloConfig { useLocalhostClustering useMutualTls "CN=my-silo-cert"}Mutual TLS with certificate instance
Section titled “Mutual TLS with certificate instance”siloConfig { useLocalhostClustering useMutualTlsWithCertificate cert}Warning: Always use valid certificates from a trusted CA in production. Never disable certificate validation in production environments.
Dashboard
Section titled “Dashboard”Requires Microsoft.Orleans.Dashboard.
Default options
Section titled “Default options”siloConfig { useLocalhostClustering addDashboard}Custom options
Section titled “Custom options”siloConfig { useLocalhostClustering addDashboardWithOptions 5000 // counter update interval (ms) 100 // history length false // hide trace}Map the dashboard endpoints in your ASP.NET Core pipeline with MapOrleansDashboard().
Health Checks
Section titled “Health Checks”siloConfig { useLocalhostClustering enableHealthChecks}Then map the health check endpoints in your ASP.NET Core pipeline:
app.MapHealthChecks("/health") |> ignoreStartup Tasks
Section titled “Startup Tasks”Run code when the silo starts:
siloConfig { useLocalhostClustering addStartupTask (fun sp ct -> task { let logger = sp.GetRequiredService<ILogger<_>>() logger.LogInformation("Silo started!") } :> Task)}Multiple startup tasks accumulate and run in registration order.
Grain Versioning
Section titled “Grain Versioning”Control how grains of different versions communicate during rolling upgrades:
open Orleans.FSharp.Versioning
siloConfig { useLocalhostClustering useGrainVersioning BackwardCompatible AllCompatibleVersions}Compatibility strategies:
| Strategy | Description |
|---|---|
BackwardCompatible | Older versions can call newer (default) |
StrictVersion | Only exact version matches |
AllVersions | All versions interoperate |
Version selector strategies:
| Strategy | Description |
|---|---|
AllCompatibleVersions | Random among compatible (default) |
LatestVersion | Always activate latest |
MinimumVersion | Always activate oldest |
Grain Collection Age
Section titled “Grain Collection Age”Set the global idle timeout before grain deactivation:
siloConfig { useLocalhostClustering grainCollectionAge (TimeSpan.FromMinutes 30.)}For per-grain timeouts, use deactivationTimeout in the grain { } CE.
Endpoints
Section titled “Endpoints”Cluster identity
Section titled “Cluster identity”siloConfig { useLocalhostClustering clusterId "my-cluster" serviceId "my-service" siloName "silo-1"}Ports and IP
Section titled “Ports and IP”siloConfig { useLocalhostClustering siloPort 11111 gatewayPort 30000 advertisedIpAddress "10.0.0.1"}Call Filters
Section titled “Call Filters”Incoming filters
Section titled “Incoming filters”Intercept calls arriving at a grain:
open Orleans.FSharp
let loggingFilter = Filter.incoming (fun ctx -> task { printfn "Incoming call: %s" (FilterContext.methodName ctx) do! ctx.Invoke() printfn "Call completed" })
siloConfig { useLocalhostClustering addIncomingFilter loggingFilter}Outgoing filters
Section titled “Outgoing filters”Intercept calls made from a grain to another grain:
let tracingFilter = Filter.outgoing (fun ctx -> task { // Add tracing headers do! ctx.Invoke() })
siloConfig { useLocalhostClustering addOutgoingFilter tracingFilter}Before/after filters
Section titled “Before/after filters”let timingFilter = Filter.incomingWithAround (fun ctx -> task { printfn "Before %s" (FilterContext.methodName ctx) }) (fun ctx -> task { printfn "After %s" (FilterContext.methodName ctx) })Grain Services
Section titled “Grain Services”GrainServices run on every silo. Use them for background processing:
siloConfig { useLocalhostClustering addGrainService typeof<MyBackgroundService>}Custom DI Services
Section titled “Custom DI Services”Register custom services with the host’s DI container:
siloConfig { useLocalhostClustering configureServices (fun services -> services.AddSingleton<IMyService, MyService>() |> ignore services.AddHttpClient() |> ignore)}Serilog
Section titled “Serilog”Wire Serilog as the logging provider:
siloConfig { useLocalhostClustering useSerilog}Complete Production Example
Section titled “Complete Production Example”open Systemopen Orleans.FSharpopen Orleans.FSharp.Runtimeopen Orleans.FSharp.Versioning
let redisConn = Environment.GetEnvironmentVariable("REDIS_CONNECTION")let azureConn = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION")
let config = siloConfig { // Clustering addRedisClustering redisConn clusterId "production" serviceId "my-app"
// Storage addRedisStorage "Default" redisConn addAzureBlobStorage "Archive" azureConn
// Streaming addMemoryStreams "Events" addBroadcastChannel "Notifications"
// Reminders addRedisReminderService redisConn
// Security useMutualTls "CN=orleans-silo"
// Observability enableHealthChecks addDashboard useSerilog
// Services configureServices (fun services -> services.AddHttpClient() |> ignore)
// Versioning useGrainVersioning BackwardCompatible LatestVersion
// Endpoints siloPort 11111 gatewayPort 30000
// Lifecycle grainCollectionAge (TimeSpan.FromHours 2.) addStartupTask (fun sp ct -> task { printfn "Silo started" } :> Threading.Tasks.Task)}Next steps
Section titled “Next steps”- Client Configuration — configure Orleans clients
- Grain Definition — define grains that use these providers
- Streaming — publish and subscribe to events
- Security — TLS, mTLS, and call filters in depth