Skip to content
Orleans.FSharp

Orleans.FSharp 5.0.1 is the current published stable release. This page records its verified production boundaries and the status of earlier release lines.

Channel Status Use it for
Orleans.FSharp 5.0.1 Published stable New applications and production evaluation
Orleans.FSharp 5.0.0 Superseded Existing applications; its project template has the startup defect documented below
Orleans.FSharp 4.1.0 Superseded stable line Existing applications preparing a 5.0 migration
Legacy authoring models Archived and unsupported Migration reference for existing applications only

The current documentation describes 5.0.1. For immutable release documentation, read the repository at the v5.0.1 tag. Applications remaining on 4.1 should use the documentation at the v4.1.0 tag while planning their migration.

The runtime APIs are unchanged from 5.0.0. Version 5.0.1 corrects the packaged project template and adds startup regression coverage to the release gate.

The Legacy archive receives no new Legacy release line, features, compatibility work, or security fixes. New applications should use grainContract, grainFor, journaledGrainFor, typed API records, and FunctionalGrain.ref.

The 5.0.0 project template needs a one-line contract correction

Section titled “The 5.0.0 project template needs a one-line contract correction”

History and existing-app workaround. The published Orleans.FSharp.Templates 5.0.0 package omits readOnly (_.value) from CounterApi.contract in src/<App>.Grains/CounterGrain.fs. The project builds and its five pure transition tests pass, but starting its silo fails because handleQuery requires a read-only operation. This defect is fixed in Orleans.FSharp.Templates 5.0.1.

For an application already generated with the 5.0.0 template, add readOnly (_.value) inside that contract, immediately after int64Key, then rebuild and run the application. Updating the template package does not rewrite existing source, so those applications still need this correction; the core 5.0.0 runtime packages do not. The 5.0.1 template is covered by a regression test that initializes the grain definition and an end-to-end template process check in the release gate.

TaskSeq is an upstream boundary when wrapping streaming replies

Section titled “TaskSeq is an upstream boundary when wrapping streaming replies”

Direct enumeration of a functional streaming reply is the supported path. With FSharp.Control.TaskSeq 1.1.1 on the repository’s verified static resumable-code path, wrapping a runtime-returned IAsyncEnumerable with TaskSeq.map or taskSeq { for item in upstream do yield item } was measured duplicating the final item. TaskSeq over ordinary producers such as lists, ranges, and database cursors is not affected.

When one grain relays another grain’s streaming reply, return a direct delegating IAsyncEnumerable/enumerator instead of using those wrapping forms. The exact pattern and the SDK boundary are documented under Authoring a producer.

Stream.asTaskSeq and its cursor-preserving Stream.asTaskSeqWithToken variant are separate Orleans pub/sub adapters. In 5.0.0 they create the subscription on first enumeration and dispose that subscription when enumeration ends, including early exit.

Functional persistence payloads are bounded per codec

Section titled “Functional persistence payloads are bounded per codec”

Orleans.FSharp 5.0.1 defaults to 16 MiB for one encoded functional state value, journal event, or snapshot. Enveloped payloads are checked before decoding and before writing. Direct binary state keeps its old provider schema: its logical Orleans encoding is checked after the provider loads the value and before each explicit write. Pre-decode protection for that direct format belongs to the provider serializer. This is a per-payload guard, not a quota for a whole grain, storage record, journal, provider, or process memory.

Use an immutable per-codec override only after validating the storage provider and memory budget:

let largeJsonCodec =
FunctionalPersistenceCodec.FSharpJson
.WithMaxPayloadBytes(64 * 1024 * 1024)

The normal resolution order is unchanged: persistent-state element, grain definition, then silo default; journal definition, then silo default. The provider-wide FSharpJsonGrainStorageSerializer has its own 16 MiB default and constructor override because it controls the complete provider value rather than a functional envelope payload. These limits were introduced in 5.0.0 and are not part of the 4.1 package.

Generalized binary payloads reject unsafe graphs

Section titled “Generalized binary payloads reject unsafe graphs”

The 5.0 binary codec preserves repeated generalized values in Orleans’ surrounding serializer session, including values held by a generated C# or F# object. Inside one opaque F# payload, cycles are rejected, nesting is capped at 128 codec calls on write and read, and repeated mutable children decode independently. This is a bounded value codec, not a native identity-preserving graph format; use generated Orleans serialization when internal object identity is required.

The same release fixes field-only and property-based CLR class reconstruction, exact-width enum values, and runtime cases of closed generic unions without changing historical property-POCO wire bytes. The precise contract is in Serialization.

Stateless-worker implicit streams require Orleans 10.3+

Section titled “Stateless-worker implicit streams require Orleans 10.3+”

In 5.0.0, a grainFor definition can combine statelessWorker with onStream when the loaded Orleans.Streaming runtime is 10.3.0 or newer. Orleans treats the local worker activations as competing consumers, so one stream item is handled by one available worker; do not assume that all local activations receive a copy.

The Orleans.FSharp package floor remains 10.1.0. On Orleans 10.1/10.2, or when the streaming package version cannot be established, definition sealing rejects this combination with a version diagnostic instead of failing later during activation. statelessWorker plus onBroadcast remains unsupported on every supported Orleans version because broadcast channels did not gain equivalent stateless-worker semantics.

This capability shipped in 5.0.0 and has a live Orleans 10.3 integration test. It is not part of the 4.1 package.

Since 5.0.0, Orleans.FSharp also exposes Orleans’ complete stateless-worker placement setting: statelessWorker maxLocalWorkers preserves the stock removeIdleWorkers = true default, while statelessWorker maxLocalWorkers false allows a functional definition to use collectionAge. The generated manifest is checked against the corresponding live Orleans attribute on both ends of the supported version matrix.

Passing unit, integration, rolling-update, website, and link checks does not certify every third-party provider, deployment topology, persisted application schema, or workload size. Before production, test the selected providers, payload distribution, failure recovery, observability, and N/N+1 rollback path with representative data.