Orleans.StateMachineES

Production-ready state machines for Microsoft Orleans

Orleans.StateMachineES brings the power of state machines to your Orleans applications, wrapping the battle-tested Stateless library with Orleans-native async APIs, event sourcing, and advanced distributed patterns.

Why Orleans.StateMachineES?

Build reliable, maintainable distributed systems with:

  • Compile-time Safety: 10 Roslyn analyzers catch state machine anti-patterns before they reach production
  • Event Sourcing Built-in: Complete state history with replay capabilities - and it's 30% faster than regular state machines
  • Production Resilience: Circuit breakers, retries, validation components, and distributed tracing out of the box
  • Advanced Patterns: Hierarchical states, distributed sagas, orthogonal regions, and versioning
  • High Performance: TriggerParameterCache provides ~100x speedup for parameterized triggers, optimized object pooling

Quick Start

Installation

dotnet add package Orleans.StateMachineES
dotnet add package Orleans.StateMachineES.Generators

Your First State Machine

using Orleans.StateMachineES;

public enum OrderState { Pending, Confirmed, Shipped, Delivered }
public enum OrderTrigger { Confirm, Ship, Deliver }

public interface IOrderGrain : IStateMachineGrain<OrderState, OrderTrigger>
{
}

public class OrderGrain : StateMachineGrain<OrderState, OrderTrigger>, IOrderGrain
{
    protected override void BuildStateMachine()
    {
        StateMachine.Configure(OrderState.Pending)
            .Permit(OrderTrigger.Confirm, OrderState.Confirmed)
            .OnEntry(() => GrainFactory.GetGrain<INotificationGrain>(0)
                .SendEmailAsync("Order received!"));

        StateMachine.Configure(OrderState.Confirmed)
            .Permit(OrderTrigger.Ship, OrderState.Shipped);

        StateMachine.Configure(OrderState.Shipped)
            .Permit(OrderTrigger.Deliver, OrderState.Delivered);
    }
}

Usage

var order = grainFactory.GetGrain<IOrderGrain>(orderId);

// Fire transitions
await order.FireAsync(OrderTrigger.Confirm);
await order.FireAsync(OrderTrigger.Ship);

// Query state
var currentState = await order.GetStateAsync(); // OrderState.Shipped
var canDeliver = await order.CanFireAsync(OrderTrigger.Deliver); // true
var permitted = await order.GetPermittedTriggersAsync(); // [OrderTrigger.Deliver]

Learn more in the Getting Started guide →

Key Features

Core State Machines

The foundation of distributed state management with Orleans.

  • StateMachineGrain Base Class: Orleans-native async state machine grain
  • Parameterized Triggers: Pass up to 3 typed arguments with transitions
  • Guard Conditions: Validate transitions with business logic
  • State Inspection: Query current state, permitted triggers, and guard status

Explore Core Concepts →

Event Sourcing

Complete state history and replay capabilities - 30.4% faster than regular state machines.

public class OrderGrain : EventSourcedStateMachineGrain<OrderState, OrderTrigger>
{
    // Automatic event persistence and replay
    // Use AutoConfirmEvents = true for maximum performance
}
  • Automatic Event Persistence: All transitions saved as events
  • State Replay: Rebuild grain state from event history
  • Idempotency: Safe re-execution of transitions
  • Stream Publishing: Orleans streams integration

Learn about Event Sourcing →

Advanced Patterns

Hierarchical States: Parent-child state relationships with substates

StateMachine.Configure(OrderState.InTransit)
    .SubstateOf(OrderState.Active)
    .Permit(OrderTrigger.Delay, OrderState.Delayed);

Distributed Sagas: Multi-grain workflows with compensation

var saga = new OrderSaga();
await saga.ExecuteAsync(context);
// Automatic compensation on failure

Orthogonal Regions: Parallel independent state machines

var regions = new OrthogonalRegions<SmartHomeState, SmartHomeTrigger>();
regions.AddRegion("Lighting", lightingStateMachine);
regions.AddRegion("Climate", climateStateMachine);

Explore Advanced Patterns →

Production Features

Circuit Breaker: Prevent cascading failures

var circuitBreaker = new CircuitBreakerComponent<State, Trigger>(new()
{
    FailureThreshold = 5,
    SuccessThreshold = 2,
    OpenDuration = TimeSpan.FromSeconds(30)
});

Distributed Tracing: OpenTelemetry integration for observability

Health Checks: ASP.NET Core health monitoring

Versioning: Manage state machine evolution across deployments

Read Production Guide →

Compile-time Safety

10 Roslyn analyzers catch issues before deployment:

Analyzer Description
OSMES001 Prevents async lambdas in callbacks
OSMES002 Blocks FireAsync in state callbacks
OSMES003 Requires BuildStateMachine implementation
OSMES004 Detects unreachable states
OSMES009 Ensures initial state is set
...and 5 more See all analyzers →

Visualization

Generate diagrams from your state machines:

var visualization = new StateMachineVisualization<State, Trigger>(stateMachine);
var mermaid = visualization.GenerateMermaidDiagram();
var dot = visualization.GenerateDotGraph();
var plantuml = visualization.GeneratePlantUmlDiagram();
var html = visualization.GenerateHtmlDiagram();

Learn about Visualization →

Performance

Optimized for production workloads:

  • Event Sourcing: 5,923 transitions/sec (30% faster than regular grains)
  • TriggerParameterCache: ~100x performance improvement for parameterized triggers
  • ValueTask: Zero-allocation paths for synchronous operations
  • FrozenCollections: 40%+ faster lookups in .NET 8+
  • Object Pooling: Thread-safe, high-performance resource management

Read Performance Guide →

Complete Examples

Explore production-ready applications:

Browse all examples →

Documentation

For Developers

For Architects

For Contributors

API Reference

Browse the complete API documentation for all packages:

Explore API Reference →

Version Information

Current Version: 1.0.4 (Released November 2025)

Latest Improvements:

  • Event sourcing performance: 30.4% faster with AutoConfirmEvents
  • Enhanced production resilience components
  • Comprehensive analyzer suite (10 analyzers)
  • Performance optimizations across the board

View Changelog | Migration Guide

Community & Support

License

Orleans.StateMachineES is licensed under the MIT License.


Ready to get started? Install Orleans.StateMachineES →