Running a cluster of Microsoft Orleans Virtual Actors

Dina Bogdan
8 min readJul 7, 2022


This article is a continuation of the initial article that discussed the intro to Virtual Actors and Microsoft Orleans.

The first article was presenting some general concepts and also a demo application that was leveraging some of Microsoft Orleans’ features (clustering, persistence, etc). Still, some details were left out of the scope of that article. In the current blog post we will cover the following:

  • setup the database used by Microsoft Orleans
  • understand the database schema and tables used by Microsoft Orleans
  • run the demo with one Microsoft Orleans silo
  • start a cluster of Microsoft Orleans silos
  • run the demo again with the cluster up-and-running

Microsoft Orleans database setup

In the past article, we were presenting a demo that was connecting to a SQL Server Database. If some of you tried to start the demo, they would have faced the following error:

This is because the database to which we are connecting it’s not properly initialized in order to be used by the Microsoft Orleans cluster.

For initializing the database, first of all, we need to have a direct connection to it and be able to run some SQL scripts. You can do this by using Microsoft SQL Server Management Studio (SSMS).

After having a SQL editor available in SSMS, please create a database having the name as specified in our ConnectionString variable from the codebase. In our specific case, the name of the database that needs to be created will be Orleans.

That’s how it should look like in SSMS after the database was created:

Now, the next step that we need to do is to configure and set up the Orleans database, by following the instructions from the official Microsoft Orleans documentation regarding ADO.NET database configuration.

Accessing the above-mentioned link, we will see that there are four sections that needs to be followed:

  • Main scripts
  • Clustering
  • Persistence
  • Reminders

We need to download the scripts according to our database technology that we are using from each of those sections and run them in a SQL Editor opened for the Orleans database. As an example, from the Main scripts section we will take the SQL-Server.sql script and run it on top of our database.

Tables used by Microsoft Orleans

After all the scripts have been executed, we should check and find that our database contains some newly-created tables, like in the following image:

Main tables

The first table that will be created will be OrleansQuery, this one being contained in the Main scripts section and being used for operational queries performed by the Microsoft Orleans cluster that you will run.

Clustering tables

The next tables that will be created are responsible with clustering in Microsoft Orleans.

First of those that needs to be created is OrleansMembershipVersionTable and it is the table that will store one row for each Orleans cluster that will be deployed and that’s connecting to this databases. It is important to know that this table it’s containing a column called Version that will have the version number of the cluster that was deployed.

As an example, our cluster is called SiloDemoCluster and here is how it looks the table mentioned above, after multiple deployments of the cluster.

The next table that’s part of the clustering section is OrleansMembershipTable and this one is designed to contain one row for each member of a cluster. Basically, each silo instance will be represented by a row in this table.

Below we can see that for SiloDemoCluster we’ve had two silo instances that were running at some point in time, one of them running behind port 11111 (the red one), while the other was using port 11112 (the green one). Also, we can see that those silos were instantiated for multiple times, because they are having different SiloName value from one row to another.

Storage tables

Next table that will be discussed is the storage one and it’s named OrleansStorage. This table is being used for storing the state of the persistent grains.

The way that this table is working is the following one: for each grain instance, that’s identified by the value of the columns GrainIdHash or GrainIdExtensionString we will have one row that will contain the value of the grain state persisted in a specific format: binary, XML or JSON. The state is persisted as the value of the column PayloadBinary, PayloadXml or PayloadJson.

Also, it’s worth mentioning that the grain state is being versioned during time, version being just a counter incremented each time when the state of the grain is changed and persisted in the table. The version number is stored in Version column.

As an example, please see how the rows of this table are looking after running our demo app.

Reminders tables

The last table that will be introduced is the OrleansRemindersTable and this one is to be used when we will work with Microsoft Orleans’s Timers & Reminders features.

We won’t discuss too much about this table since we are not using this feature (yet) in our demo app.

Demo with one Silo

For seeing how our demo is working we need to turn it on. We will start by using a single Silo in the very beginning, but be patient, we will soon scale up our cluster.

First of all, we need to turn on our Silo project and for this we need to run the Program.cs file. As you can see in the codebase, running the Program.cs needs some arguments. Please provide 11111 as input arguments in Visual Studio as described here. The effect of this is that we will run our silo beneath porth 11111.

If the output to the console isn’t showing any red error message and it’s similar to the below one, then everything was successful. Please note that in the red rectangle you can see that a new silo instance was start on port 11111.

Console output for one silo instance

Now you can go and check the OrleansMembershipTable and OrleansMembershipVersionTable to see what values were recently insterted in.

Now, let’s run the client app, this being the DistributedCounterWebApi project.

Right after running the web app, please check the logs of the Silo. You will see that a new Microsoft Orleans connection was opened, as in the below picture.

Microsoft Orleans client connected

Now, try incrementing or decrementing the counter by using the exposed Swagger interface of our Web API and then check the logs of the Silo. You’ll see that one grain was initialized, like below.

New grain initialization

After decremeting and incrementing the value of the grain, take the grain key that you’ve used and check the rows in the OrleansStorage table. You’ll see the changes the effects that you have produced.

Start a Microsoft Orleans cluster

Currently, we are running only a single-node cluster of Microsoft Orleans, but this can be changed by starting another silo instance.

For this, we simply need to provide another command-line argument for starting the silo on a different port, rather than 11111 which is currently busy with our initial silo instance. Start a new Visual Studio instance, change the port number to 11112 and run the Silo project one more time.

After running the second silo instance, another console will pop-up in front of us and we will see an output like below.

Console output for the second silo instance

Please note that with red is marked the fact that the silo instance was started on the desired port number, while with green is market the fact that the cluster was formed with our initial member.

Go and check the rows from the OrleansMembershipTable and you’ll see that some new row was added for the silo running on port 11112.

Demo again

Now, since we are currently having a Microsoft Orleans cluster with two active members, let’s try incrementing and decrementing the counter one more time.

For our initial key, execute some more operations. You’ll see that the value of the counter was changed, but there isn’t any new log line printed out.

Create a new counter by changing the value of the key that’s used in the Web API. For this newly-created counter, you’ll see that the silo that’s being used is the second instance that we have started. This is demonstrating how Microsoft Orleans is distributing the load across all cluster members.

In red rectangle we can see the output from the initial silo instance, the key that was used being “zzz”, while in green rectangle we have the output for the second silo instance with key value “yyy”.

Don’t forget to check the rows in the OrleansStorage table one more time.


  • there is a complex database set up that needs to be done before running a Microsoft Orleans cluster, when using ADO.NET for clustering and persistence features;
  • the tables that needs to be created before running our Microsoft Orleans cluster are having specific responsibilities and those have been discussed in the current article;
  • running a Microsoft Orleans cluster with one silo is possible, but not recommended because all the load will be handled by a single instance;
  • starting multiple Microsoft Orleans silos will allow those to create a cluster and the load will be distributed across all the members.

Don’t forget to follow me on Twitter!



Dina Bogdan

Living in a reactive, full of actors, distributed system.