Deploy and scale an Orleans app on Azure
In this quickstart, you deploy and scale an Orleans URL shortener app on Azure Container Apps. The app allows users to submit a full URL to the app, which returns a shortened version they can share with others to direct them to the original site. Orleans and Azure provide the scalability features necessary to host high traffic apps like URL shorteners. Orleans is also compatible with any other hosting service that supports .NET.
At the end of this quickstart, you have a scalable app running in Azure to provide URL shortener functionality. Along the way you learn to:
- Pull and Azure Developer CLI template
- Deploy an Orleans app to Azure
- Scale the app to multiple instances
Prerequisites
Section titled “Prerequisites”- An Azure account with an active subscription. Create an account for free.
- Azure Developer CLI
- .NET 8
- Docker
Get and deploy the sample application
Section titled “Get and deploy the sample application”The sample application is available as an Azure Developer CLI template. Through this quickstart: you pull the template application, deploy the template and sample code to Azure, change the template to implement your preferred persistence grain, deploy the necessary resources, and then deploy the final application.
-
Open a terminal in an empty directory.
-
Authenticate to the Azure Developer CLI using
azd auth login. Follow the steps specified by the tool to authenticate to the CLI using your preferred Azure credentials.Terminal window azd auth login -
Get the sample application using the AZD template
orleans-url-shortenerand theazd initcommand.Terminal window azd init --template orleans-url-shortener -
During initialization, configure a unique environment name.
-
Deploy the Azure Cosmos DB for NoSQL account using
azd up. The Bicep templates also deploy a sample web application.Terminal window azd up -
During the provisioning process, select your subscription and desired location. Wait for the provisioning and deployment process to complete. The process can take approximately five minutes.
-
Once the provisioning of your Azure resources is done, a URL to the running web application is included in the output.
Deploying services (azd deploy)(✓) Done: Deploying service web- Endpoint: <https://[container-app-sub-domain].azurecontainerapps.io>SUCCESS: Your application was provisioned and deployed to Azure in 5 minutes 0 seconds. -
Use the URL in the console to navigate to your web application in the browser.

-
In the browser address bar, test the
shortenendpoint by adding a URL path such as/shorten?url=https://www.microsoft.com. The page should reload and provide a new URL with a shortened path at the end. Copy the new URL to your clipboard.{"original": "https://www.microsoft.com","shortened": "http://<container-app-name>.<deployment-name>.<region>.azurecontainerapps.io:<port>/go/<generated-id>"} -
Paste the shortened URL into the address bar and press enter. The page should reload and redirect you to the URL you specified.
Deploy extra services
Section titled “Deploy extra services”The original deployment only deployed the minimal services necessary to host the URL shortener app. To use an Azure data service for grain persistence, you must first configure the template to deploy your preferred service.
Applies to: Azure Storage
-
Using the terminal, run
azd env setto configure theDEPLOY_AZURE_TABLE_STORAGEenvironment variable to enable deployment of Azure Cosmos DB for NoSQL.Terminal window azd env set DEPLOY_AZURE_TABLE_STORAGE true
Applies to: Azure Cosmos DB for NoSQL
-
Using the terminal, run
azd env setto configure theDEPLOY_AZURE_COSMOS_DB_NOSQLenvironment variable to enable deployment of Azure Cosmos DB for NoSQL.Terminal window azd env set DEPLOY_AZURE_COSMOS_DB_NOSQL true
-
Run
azd provisionto redeploy your application architecture with the new configuration. Wait for the provisioning process to complete. The process can take approximately two minutes.Terminal window azd provision
Install NuGet packages
Section titled “Install NuGet packages”Prior to using the grain, you must install the corresponding Microsoft.Orleans.Clustering.* and Microsoft.Orleans.Persistence.* NuGet packages. These services use role-based access control for passwordless authentication, so you must also import the Azure.Identity NuGet package.
Applies to: Azure Storage
-
Change your current working directory to ./src/web/.
Terminal window cd ./src/web -
Import the
Azure.Identitypackage from NuGet:Terminal window dotnet add package Azure.Identity --version 1.* -
Import the
Microsoft.Orleans.Clustering.AzureStorageandMicrosoft.Orleans.Persistence.AzureStoragepackages.Feature NuGet package Clustering Microsoft.Orleans.Clustering.AzureStoragePersistence Microsoft.Orleans.Persistence.AzureStorageTerminal window dotnet add package Microsoft.Orleans.Clustering.AzureStorage --version 8.*dotnet add package Microsoft.Orleans.Persistence.AzureStorage --version 8.*
Applies to: Azure Cosmos DB for NoSQL
-
Import the
Azure.Identitypackage from NuGet:Terminal window dotnet add package Azure.Identity --version 1.* -
Import the
Microsoft.Orleans.Clustering.CosmosandMicrosoft.Orleans.Persistence.Cosmospackages.Feature NuGet package Clustering Microsoft.Orleans.Clustering.CosmosPersistence Microsoft.Orleans.Persistence.CosmosTerminal window dotnet add package Microsoft.Orleans.Clustering.Cosmos --version 8.*dotnet add package Microsoft.Orleans.Persistence.Cosmos --version 8.*
Configure and redeploy the sample app
Section titled “Configure and redeploy the sample app”The sample app is currently configured to create a localhost cluster and persist grains in-memory. When hosted in Azure, Orleans can be configured to use more scalable, centralized state using a data service in Azure.
-
Add the following
usingdirectives:using Azure.Identity;using Orleans.Configuration; -
Find and remove the current
builderconfiguration code in the src/web/Program.cs file.builder.Host.UseOrleans(static siloBuilder =>{siloBuilder.UseLocalhostClustering().AddMemoryGrainStorage("urls");});
Applies to: Azure Storage
-
Replace the
builderconfiguration with the example here, which implements these key concepts:- A conditional environment check is added to ensure the app runs properly in both local development and Azure hosted scenarios.
- The
UseAzureStorageClusteringmethod configures the Orleans cluster to use Azure Table Storage and authenticates using the DefaultAzureCredential class. - Use the
Configuremethod to assign IDs for the Orleans cluster. - The
ClusterIDis a unique ID for the cluster that allows clients and silos to talk to one another. - The
ClusterIDcan change across deployments. - The
ServiceIDis a unique ID for the application that is used internally by Orleans and should remain consistent across deployments.
if (builder.Environment.IsDevelopment()){builder.Host.UseOrleans(static siloBuilder =>{siloBuilder.UseLocalhostClustering().AddMemoryGrainStorage("urls");});}else{builder.Host.UseOrleans(siloBuilder =>{var endpoint = new Uri(builder.Configuration["AZURE_TABLE_STORAGE_ENDPOINT"]!);var credential = new DefaultAzureCredential();siloBuilder.UseAzureStorageClustering(options =>{options.ConfigureTableServiceClient(endpoint, credential);}).AddAzureTableGrainStorage(name: "urls", options =>{options.ConfigureTableServiceClient(endpoint, credential);}).Configure<ClusterOptions>(options =>{options.ClusterId = "url-shortener";options.ServiceId = "urls";});});}
Applies to: Azure Cosmos DB for NoSQL
-
Replace the
builderconfiguration with the example here, which implements these key concepts:- A conditional environment check is added to ensure the app runs properly in both local development and Azure hosted scenarios.
- The
UseCosmosClusteringmethod configures the Orleans cluster to use Azure Cosmos DB for NoSQL and authenticates using the DefaultAzureCredential class. - Use the
Configuremethod to assign IDs for the Orleans cluster. - The
ClusterIDis a unique ID for the cluster that allows clients and silos to talk to one another. - The
ClusterIDcan change across deployments. - The
ServiceIDis a unique ID for the application that is used internally by Orleans and should remain consistent across deployments.
if (builder.Environment.IsDevelopment()){builder.Host.UseOrleans(static siloBuilder =>{siloBuilder.UseLocalhostClustering().AddMemoryGrainStorage("urls");});}else{builder.Host.UseOrleans(siloBuilder =>{var endpoint = builder.Configuration["AZURE_COSMOS_DB_NOSQL_ENDPOINT"]!;var credential = new DefaultAzureCredential();siloBuilder.UseCosmosClustering(options =>{options.ConfigureCosmosClient(endpoint, credential);}).AddCosmosGrainStorage(name: "urls", options =>{options.ConfigureCosmosClient(endpoint, credential);}).Configure<ClusterOptions>(options =>{options.ClusterId = "url-shortener";options.ServiceId = "urls";});});}
-
Run
azd deployto redeploy your application code as a Docker container. Wait for the deployment process to complete. The process can take approximately one minute.Terminal window azd deploy
Verify the app’s behavior
Section titled “Verify the app’s behavior”Validate that your updated code works by using the deployed application again and checking to see where it stores data.
-
In the browser address bar, test the
shortenendpoint again by adding a URL path such as/shorten?url=https://learn.microsoft.com/dotnet/orleans. The page should reload and provide a new URL with a shortened path at the end. Copy the new URL to your clipboard.{"original": "https://learn.microsoft.com/dotnet/orleans","shortened": "http://<container-app-name>.<deployment-name>.<region>.azurecontainerapps.io:<port>/go/<generated-id>"} -
Paste the shortened URL into the address bar and press enter. The page should reload and redirect you to the URL you specified.
Optionally, you can verify that the cluster and state data is stored as expected in the storage account you created.
-
In the Azure portal, navigate to the resource group that was deployed in this quickstart.
Applies to: Azure Storage
-
Navigate to the overview page of the Azure Storage account.
-
Within the navigation, select Storage browser.
-
Expand the Tables navigation item to discover two tables created by Orleans:
- OrleansGrainState: This table stores the persistent state grain data used by the application to handle the URL redirects.
- OrleansSiloInstances: This table tracks essential silo data for the Orleans cluster.
-
Select the OrleansGrainState table. The table holds a row entry for every URL redirect persisted by the app during your testing.

Applies to: Azure Cosmos DB for NoSQL
-
Navigate to the overview page of the Azure Cosmos DB for NoSQL account.
-
Within the navigation,select Data Explorer.
-
Observe the following containers you created earlier in this guide:
-
OrleansStorage: This table stores the persistent state grain data used by the application to handle the URL redirects.
-
OrleansCluster: This table tracks essential silo data for the Orleans cluster.
-
Scale the app
Section titled “Scale the app”Orleans is designed for distributed applications. Even an app as simple as the URL shortener can benefit from the scalability of Orleans. You can scale and test your app across multiple instances using the following steps:
-
Navigate back to the resource group that was deployed in this quickstart.
-
Navigate to the overview page of the Azure Container Apps app.
-
Within the navigation, select Scale.
-
Select Edit and deploy, and then switch to the Scale tab.
-
Use the slider control to set the min and max replica values to 4. This value ensures the app is running on multiple instances.
-
Select Create to deploy the new revision.

-
After the deployment is finished, repeat the testing steps from the previous section. The app continues to work as expected across several instances and can now handle a higher number of requests.
Related content
Section titled “Related content”Applies to: Azure Storage
Applies to: Azure Cosmos DB for NoSQL
