Skip to content

Build and deploy a production-shaped Orleans application

This walkthrough takes you from an empty directory to a deployed, observable Orleans cluster. You use the maintained Azure Container Apps sample so that the application, infrastructure, and deployment workflow stay buildable together.

The finished system has dedicated silos, an HTTP API and worker client, Azure Table Storage clustering, managed identity, health probes, Application Insights, and an Orleans Dashboard. This sample demonstrates clustering and deployment; add a grain-storage provider to persist application state.

From an empty working directory:

Terminal window
git clone https://github.com/dotnet/orleans.git
cd orleans
dotnet build .\samples\Deployment\AzureContainerApps\HelloOrleans.sln -c Release

Explore the projects before running them:

ProjectResponsibility
AbstractionsGrain interfaces and serialized contracts shared by callers and silos.
GrainsGrain implementations and placement policy.
SiloA dedicated Orleans server process.
Clients.MinimalApiAn HTTP API which calls grains through an Orleans client.
Clients.WorkerServiceA background client which sends simulated sensor updates.
DashboardA separately deployed dashboard silo.
InfrastructureShared identity, clustering, endpoint, and telemetry configuration.

This separation lets clients and silos scale and deploy independently. It also keeps contracts independent from implementations.

Start Azurite, then open four terminals at the repository root:

Terminal window
dotnet run --project .\samples\Deployment\AzureContainerApps\Silo
dotnet run --project .\samples\Deployment\AzureContainerApps\Dashboard
dotnet run --project .\samples\Deployment\AzureContainerApps\Clients.MinimalApi
dotnet run --project .\samples\Deployment\AzureContainerApps\Clients.WorkerService

Each launch profile selects the Development environment and connects to Azurite. Verify the system before deploying:

  1. Open the dashboard URL printed by the Dashboard process and confirm that its silo and the dedicated silo are active.
  2. Call GET /hello/0 on the Minimal API and confirm that it returns a greeting.
  3. Call GET /providers and confirm that grain key 0 appears.
  4. Stop the worker and confirm that API calls continue; the worker and Minimal API are separate Orleans clients, so restarting the worker leaves the API client connected to the silo cluster.

The sample dashboard uses open access for local development. Keep that endpoint on a trusted local host. For a deployed environment, secure the dashboard with HTTPS, operator authentication and authorization, and a private administrative path.

Development uses a storage emulator. Deployed processes use DefaultAzureCredential with a user-assigned managed identity and an Azure Table service URI. Token-based data-plane access supplies storage authorization.

Every deployed silo has a unique advertised silo and gateway endpoint. Azure Container Apps assigns the documented endpoint at the app boundary, so the sample deploys each silo as a separate one-replica Container App. Add capacity by adding silo apps with unused ports.

Review the sample’s deployment README and Azure/bootstrap.bicep before assigning roles. The privileged bootstrap and routine deployment are deliberately separate.

  1. Fork the Orleans repository and enable GitHub Actions.
  2. Configure a GitHub OIDC identity restricted to your fork and a protected azure-container-apps environment.
  3. Run the sample’s one-time privileged bootstrap to create the registry, membership storage, runtime identity, and least-privilege role assignments.
  4. Copy samples/Deployment/AzureContainerApps/deployment/deploy.yml to .github/workflows/deploy-orleans-container-apps.yml.
  5. Configure the dashboard host and ingress for the operator controls described above.
  6. Add the environment variables listed in the sample README, then run the workflow.

The workflow builds images, pushes immutable Git-SHA tags, deploys by image digest, and authenticates through GitHub OIDC and workload identity.

Connect through the operator-only administrative path, then:

  1. Confirm that every expected silo is active in the dashboard.
  2. Exercise GET /hello/0, GET /hello/255, and GET /providers.
  3. Verify that invalid grain keys return HTTP 400.
  4. Confirm that startup, readiness, and liveness probes are healthy.
  5. Inspect traces and logs in Application Insights and confirm that requests cross the API-to-grain boundary.

Before adapting this system for production, work through the production-readiness checklist, configure durable grain storage, and plan graceful shutdown and upgrades.