Microsoft.Orleans.Journaling 10.2.0-alpha.1

Microsoft Orleans Journaling

Introduction

Microsoft Orleans Journaling persists durable state changes as ordered journal data which can be replayed to recover in-memory durable collections and values.

The package includes a JSON Lines-based storage format powered by System.Text.Json and uses it by default. Pair it with a Journaling storage provider such as Microsoft.Orleans.Journaling.AzureStorage. The storage provider remains independent of the serialization format: Microsoft.Orleans.Journaling supplies the journal format and keyed durable-entry codecs which durable states use to encode and recover their own operations.

Getting Started

To use this package, install it via NuGet:

dotnet add package Microsoft.Orleans.Journaling

Example - Configuring JSON journaling

using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.Hosting;
using Orleans.Hosting;
using Orleans.Journaling;
using Orleans.Journaling.Json;

[JsonSerializable(typeof(DateTime))]
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(ulong))]
internal partial class JournalJsonContext : JsonSerializerContext;

var builder = Host.CreateApplicationBuilder(args)
    .UseOrleans(siloBuilder =>
    {
        siloBuilder
            .UseLocalhostClustering()
            .AddAzureBlobJournalStorage()
            .UseJsonJournalFormat(JournalJsonContext.Default);
    });

await builder.Build().RunAsync();

If you need to customize JsonSerializerOptions, configure JsonJournalOptions through the options pipeline:

siloBuilder
    .AddAzureBlobJournalStorage()
    .Configure<JsonJournalOptions>(options =>
    {
        options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        options.AddTypeInfoResolver(JournalJsonContext.Default);
    });

JSON Lines is the default JournaledStateManagerOptions.JournalFormatKey. Storage providers can persist the journal format key as metadata alongside journal bytes. During recovery, Orleans uses that stored key to select the matching journal format and durable operation codecs. If a non-empty journal has no stored format metadata, Orleans treats it as legacy OrleansBinary data for compatibility.

If you already have data written with the OrleansBinary format, you can keep using it while you plan a migration:

siloBuilder
    .AddAzureBlobJournalStorage()
    .ConfigureServices(services =>
        services.Configure<JournaledStateManagerOptions>(options =>
            options.JournalFormatKey = "orleans-binary"));

To migrate to JSON, configure JournaledStateManagerOptions.JournalFormatKey to JsonJournalExtensions.JournalFormatKey and call UseJsonJournalFormat(...). When a grain recovers data written with a different format than the configured write format, the next write is forced to a full snapshot so the journal is rewritten using JSON and the storage format metadata is updated.

Example - Using durable states

using Microsoft.Extensions.DependencyInjection;
using Orleans.Journaling;

public interface IShoppingCartGrain : IGrainWithStringKey
{
    ValueTask AddItem(string itemId, int quantity);
    ValueTask<Dictionary<string, int>> GetItems();
}

public sealed class ShoppingCartGrain(
    [FromKeyedServices("cart")] IDurableDictionary<string, int> cart)
    : DurableGrain, IShoppingCartGrain
{
    public async ValueTask AddItem(string itemId, int quantity)
    {
        cart[itemId] = quantity;
        await WriteStateAsync();
    }

    public ValueTask<Dictionary<string, int>> GetItems() => new(cart.ToDictionary());
}

All durable state types use the configured JSON codec automatically. Configure JsonJournalOptions to control the JsonSerializerOptions instance used for entry payloads. Journaling command names and record shape are fixed by the storage format, so serializer naming policies only affect user payload values.

For trimming and Native AOT, use Configure<JsonJournalOptions>(...) to configure SerializerOptions.TypeInfoResolver, SerializerOptions.TypeInfoResolverChain, or JsonJournalOptions.AddTypeInfoResolver(...) with source-generated metadata for every journaled key, value, and state type. The UseJsonJournalFormat(JournalJsonContext.Default) overload is the recommended low-friction path when you also want to enable the JSON format explicitly. If metadata is unavailable, the JSON durable entry codecs fail with a configuration error instead of falling back to reflection-based serialization.

Storage format

The JSON journaling format stores journal entries as true JSON Lines: UTF-8 text, no byte order mark, and one JSON array per journal entry line. Each line is terminated by \n. Recovery accepts both LF and CRLF line endings. Storage providers which use format metadata should store JsonJournalExtensions.JournalFormatKey as the format key and may use application/jsonl as the MIME type.

Each record contains the state id as element 0 and the durable operation payload array as element 1:

[8,["set","alpha",1]]

Inside the operation payload array, element 0 is the command name, followed by command-specific operands such as keys, values, item arrays, or versions. Storage write batches append one or more complete JSON Lines records without adding a separate extent envelope or final container-close step.

Existing data is read using its stored format metadata, or as legacy OrleansBinary data when metadata is absent, and migrated to the configured write format by the next snapshot write.

Documentation

For more comprehensive documentation, please refer to:

Feedback & Contributing

No packages depend on Microsoft.Orleans.Journaling.

.NET 10.0

.NET 8.0

Version Downloads Last updated
10.2.0-alpha.1 2 06/16/2026
10.1.1-preview.1.alpha.1 1 06/16/2026
10.1.0-alpha.1 2 06/16/2026
10.0.1-alpha.1 1 06/16/2026
10.0.0-rc.2.alpha.1 1 06/16/2026
10.0.0-alpha.1 1 06/16/2026
9.2.1-alpha.1 1 06/16/2026
9.2.0-preview3.alpha.1 2 06/16/2026
9.2.0-preview2.alpha.1 1 06/16/2026
9.2.0-alpha.1 2 06/16/2026