Framework
dotnet/orleans avatar
dotnet/orleans

Microsoft Orleans: a .NET framework for distributed applications built on virtual actors

Cloud Native application framework for .NET

10,869 stars2,136 forksC#MIT

At a glance

What is it?
Orleans extends familiar .NET concepts to multi-server environments through grains, the silo runtime and a managed lifecycle. This review covers the programming model, how to get a first silo running, and where the framework stops being the right tool.
Who is it for?
Adopt Orleans if your domain decomposes into many independently addressable entities with their own state and you want to write that as ordinary .NET classes rather than as message-passing plumbing. Do not adopt it if your workload is a small number of long-running, tightly coupled services, or if your team cannot operate a cluster of silos and the storage behind grain persistence.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Orleans solves: stateful entities without hand-written placement code

Distributed systems in .NET traditionally push a lot of mechanical work onto the developer. You decide which process owns a piece of state, how a caller finds that process, what happens when the process dies mid-call, and when the state should be evicted from memory. Orleans removes those decisions from application code by making the unit of computation a grain: an entity with a user-defined identity, behavior and state. The README describes grains as the fundamental building block, with identities that are user-defined keys which make grains always available for invocation.

The intended audience is a .NET developer who is comfortable with objects, interfaces, async/await and try/catch and now needs those same ideas to work across many servers. Orleans is not a general-purpose messaging library and it is not an RPC framework you point at existing services. It asks you to express your domain as grains first, then gives you a runtime that handles where those grains live. The README frames the value as helping developers experienced with single-server applications transition to building cloud services, which is why the framework has been called distributed .NET.

Grains, silos and the managed lifecycle

A grain is a class that implements one or more strongly typed interfaces, and its identity comes from the interface it is invoked through. The README example uses IGrainWithStringKey, so the grain is addressed by a string. Callers never construct a grain. They ask a client or another grain for it by identity, and the runtime returns something that satisfies the interface.

The runtime component that hosts grains is the silo. A group of silos runs as a cluster for scalability and fault tolerance, and silos coordinate to distribute work and to detect and recover from failures. The README states that the runtime lets grains hosted in the cluster communicate as if they were within a single process. That is the central abstraction: the caller does not need to know which server holds a grain at any moment.

Activation is on demand. The runtime creates a grain when it is first invoked, keeps its state in memory while the grain is active, and removes grains that have not been used for a while. Because identity is stable, an invocation works whether or not the grain is currently loaded, and a failed activation can be retried transparently. The trade-off is that you give up direct control over placement and lifetime. If your workload depends on pinning a specific entity to a specific machine, or on keeping a large working set resident indefinitely, the managed lifecycle works against you. The README does not document an override for those cases in the excerpt available here.

Beyond the programming model, the silo supplies runtime services to grains. The README lists timers, reminders (persistent timers), persistence, transactions and streams among the features section.

Installing Orleans and running a first grain

Orleans ships as NuGet packages published under the Orleans profile, and the repository carries templates and samples rather than a standalone installer. The repository root contains Build.cmd, Test.cmd, TestAll.cmd and build.ps1 for building the framework itself, and a samples directory with projects such as samples/HelloWorld and samples/BasicClustering. If you want to see a working silo before writing your own, those two samples are the shortest path.

A grain contract is a plain .NET interface that derives from one of the grain key interfaces. The README gives this thermostat example, where the key is a string:

csharp
public interface IThermostat : IGrainWithStringKey
{
    Task<List<Command>> OnUpdate(ThermostatStatus update);
}

An external client obtains the grain by identity and awaits the call. The README shows the invocation in two lines:

csharp
var thermostat = client.GetGrain<IThermostat>(id);
return await thermostat.OnUpdate(update);

The implementation class inherits from Grain and implements the contract. The README example implements two interfaces on one class, so the same grain serves device traffic and control traffic:

csharp
public class ThermostatGrain : Grain, IThermostat, IThermostatControl
{
    private ThermostatStatus _status;
    private List<Command> _commands;

    public Task<List<Command>> OnUpdate(ThermostatStatus status)
    {
        _status = status;
        var result = _commands;
        _commands = new List<Command>();
        return Task.FromResult(result);
    }
}

That class keeps state in fields only. The README is explicit that this grain does not persist its state and points to the grain persistence documentation for a fuller example. Expect the fields to be lost when the grain is deactivated unless you add a storage provider. The README does not give the package names or configuration keys for that provider in the excerpt available here, so treat persistence setup as the first thing to read in the docs rather than something to guess.

Where Orleans is the wrong choice

The managed lifecycle is the source of the sharpest limitation. Grains are deactivated when idle, so any state you keep only in memory is temporary by design. Work that must survive deactivation has to go through a storage provider, and the README leaves that configuration to the persistence documentation. If your application cannot tolerate a cold read on the first invocation after deactivation, you need to plan for that latency rather than assume the grain stays warm.

Placement is also not yours to direct. The README says the runtime is responsible for activation, deactivation, placement and location. That is the feature, but it means you cannot reason about locality the way you would with a partitioned service. A workload that requires a specific grain to run next to a specific resource, or that needs strict ordering across many grains, does not map cleanly onto this model.

The framework also assumes a cluster. A single silo on one on-premises server is supported, but the coordination, failure detection and recovery machinery is only worth its complexity when you actually run several silos. For a system with a handful of long-lived services and a shared database, ordinary ASP.NET Core services plus a queue will be simpler to operate and to debug. Orleans adds a runtime between your code and your deployment, and that runtime has to be understood by whoever is on call.

Orleans compared with a plain actor toolkit such as Akka.NET

Akka.NET is the closest widely used alternative in the .NET ecosystem, and the difference is in the programming model rather than the language. Akka.NET gives you actors you create, supervise and stop explicitly, with a supervision hierarchy you design and an address you manage. Orleans gives you grains that are always addressable by identity and that the runtime activates and deactivates on demand. In Akka.NET terms, the lifecycle decisions are yours; in Orleans they belong to the silo.

That difference shows up in failure handling too. The README describes transparent recovery because the caller does not need to know which server holds a grain. There is no supervision tree to configure for the common case, and no explicit actor reference to reacquire after a crash. The cost is less control: you cannot express a supervision strategy as precisely, because the runtime owns activation.

The choice usually comes down to whether your domain has natural identities. A device, a user account, a shopping cart or a document each map to a grain with almost no translation. If your system is better described as a pipeline of stateless stages, neither framework is the right starting point.

Versioning, licence and the cost of staying current

Orleans is MIT licensed, so the framework can be used in closed-source and commercial products. The repository also carries a samples/DotnetSamples.LICENSE.txt file covering the sample code, which is worth reading separately from the root LICENSE if you intend to copy a sample into your own project. Nothing here is legal advice; check the licence text against your own distribution model.

The release cadence is visible in the repository history. v10.3.1 was released on 2026-08-28, two days after v10.3.0 on 2026-08-27, which followed a release candidate on 2026-08-25. Patch releases arriving within days of a minor release is a normal pattern for a project that fixes issues found right after a version ships. The last push to the default branch was on 2026-09-21.

Upgrade cost is concentrated in two places. The first is the package set: a solution pins versions through Directory.Packages.props and global.json, so a move between major versions is a coordinated change across every Orleans package you reference, not a single bump. The second is grain state. If you use persistence, the storage provider and the serialization of grain state are part of your upgrade surface, and changing either can require a migration path for data already written. The repository contains a durable-jobs-provider-migration-plan.md at the top level, which indicates that provider migrations are treated as planned work rather than incidental changes.

Editorial conclusion

Adopt Orleans if your domain decomposes into many independently addressable entities with their own state and you want to write that as ordinary .NET classes rather than as message-passing plumbing. Do not adopt it if your workload is a small number of long-running, tightly coupled services, or if your team cannot operate a cluster of silos and the storage behind grain persistence. Before writing code, verify three things: the target framework and package versions in global.json and Directory.Packages.props, which clustering and storage providers your deployment supports, and whether the samples/BasicClustering and samples/HelloWorld projects match the topology you intend to run.

Frequently asked questions

What is Microsoft Orleans used for?

It is a cross-platform framework for building distributed applications on .NET, intended for cloud services and other multi-server systems. Applications are expressed as grains, which the silo runtime activates, places and deactivates on demand.

How do I install Orleans in a .NET project?

Orleans is distributed as NuGet packages published under the Orleans profile, so it is added to a project through NuGet rather than through a separate installer. The repository also provides samples such as samples/HelloWorld and samples/BasicClustering that can be run directly.

Do Orleans grains keep their state when they are deactivated?

Not by default. The README states that the thermostat grain example does not persist its state, and points to the grain persistence documentation for a fuller example. State held only in fields is lost when the runtime removes the grain from memory.

What is the licence for Orleans?

The repository is MIT licensed. Sample code is covered separately by samples/DotnetSamples.LICENSE.txt, so check that file if you plan to reuse a sample.

Official sources

  1. dotnet/orleans on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dotnet-orleans.svg)](https://hysenlabs.com/projects/dotnet-orleans)