Upgrade Orleans 9.x to 10.x
Starting and target assumptions
Section titled “Starting and target assumptions”This guide assumes:
- The application runs on the latest Orleans 9.x patch, preferably Orleans 9.2.1.
- The application and its dependencies support .NET 8 or .NET 10.
- All Orleans packages in the solution will move to the same current Orleans 10.x patch.
- Provider schemas are current for the deployed Orleans 9.x version.
Orleans 10 packages target both .NET 8 and .NET 10. Retargeting the application to .NET 10 can be a separate change; keeping the application on .NET 8 reduces the number of variables in the Orleans upgrade.
Change summary
Section titled “Change summary”| Area | Orleans 10 impact | Required action |
|---|---|---|
| Source and analyzers | UnorderedAttribute and OrleansConstructorAttribute are obsolete | Remove UnorderedAttribute. Replace OrleansConstructorAttribute only when DI constructor selection is required. |
| Behavior | CancelRequestOnTimeout now defaults to false | Set it explicitly if the application depends on cancellation being sent after a timeout. |
| ADO.NET providers | SQL Server now uses Microsoft.Data.SqlClient and its invariant name by default | Replace System.Data.SqlClient, update the invariant, and test every ADO.NET provider. |
| Serialization and state | Orleans 10 doesn’t require a wire-format or grain-state rewrite from Orleans 9 | Preserve serializer IDs, aliases, provider serializer settings, and stored type compatibility. |
| Hosting | The generic-host UseOrleans and UseOrleansClient model remains current | No hosting rewrite is required for an Orleans 9 application already using these APIs. |
| Placement | Orleans 9.2 already changed the default to ResourceOptimizedPlacement | Keep it, or register RandomPlacement explicitly before the upgrade if deterministic continuity is required. |
| Cancellation | Orleans 10 adds cancellation support for observers and system targets | Keep at most one CancellationToken parameter per grain method and test timeout/cancellation races. |
| Timers | No new Orleans 10 timer break | Continue using RegisterGrainTimer; RegisterTimer was already obsolete in Orleans 8.2. |
| Call filters | No new Orleans 10 filter registration model | Continue registering incoming and outgoing filters on ISiloBuilder or IClientBuilder. |
| Deployment | Cross-major mixed clusters aren’t covered by the documented compatibility guarantee | Use a parallel Orleans 10 cluster unless your exact mixed-version topology has been qualified. |
Update packages centrally
Section titled “Update packages centrally”Keep package versions aligned. For example, with NuGet Central Package Management:
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <OrleansVersion>10.2.2</OrleansVersion> </PropertyGroup> <ItemGroup> <PackageVersion Include="Microsoft.Orleans.Client" Version="$(OrleansVersion)" /> <PackageVersion Include="Microsoft.Orleans.Sdk" Version="$(OrleansVersion)" /> <PackageVersion Include="Microsoft.Orleans.Server" Version="$(OrleansVersion)" /> </ItemGroup></Project>Use the current stable Orleans 10.x patch when you perform the migration. Add every provider package used by the solution to the same central file, using the same Orleans version.
Review source warnings
Section titled “Review source warnings”UnorderedAttribute has no effect because Orleans doesn’t guarantee message ordering based on this attribute. Remove it from grain interfaces.
Replace OrleansConstructorAttribute only for dependency injection
Section titled “Replace OrleansConstructorAttribute only for dependency injection ”OrleansConstructorAttribute is no longer recognized by Orleans. If a serializable type needs a constructor selected for dependency injection, use GeneratedActivatorConstructorAttribute or ActivatorUtilitiesConstructorAttribute. These attributes don’t select a constructor for deserializing data members.
Don’t change member IDs or constructor-visible state as part of this cleanup.
Make timeout cancellation explicit
Section titled “Make timeout cancellation explicit”Orleans 10 defaults CancelRequestOnTimeout to false. A timed-out caller therefore stops waiting, but Orleans doesn’t automatically send cancellation to the target.
public static void ConfigureTimeoutCancellation(ISiloBuilder siloBuilder){ siloBuilder.Configure<SiloMessagingOptions>(options => { options.CancelRequestOnTimeout = true; });}
public static void ConfigureTimeoutCancellation(IClientBuilder clientBuilder){ clientBuilder.Configure<ClientMessagingOptions>(options => { options.CancelRequestOnTimeout = true; });}Set this option on clients and silos that originate calls. A timeout isn’t proof that the target stopped executing, regardless of this option, so grain methods must remain safe to retry.
Update SQL Server ADO.NET configuration
Section titled “Update SQL Server ADO.NET configuration”Orleans 10 ADO.NET clustering, persistence, reminders, and streaming use Microsoft.Data.SqlClient for SQL Server.
- Remove direct
System.Data.SqlClientpackage references. - Add
Microsoft.Data.SqlClientthrough your central package policy. Use a current version supported by your application; don’t copy an old pinned version from an earlier migration guide. - Change the provider invariant from
System.Data.SqlClienttoMicrosoft.Data.SqlClient. - Apply any provider migration scripts required between the schema version currently deployed and the target Orleans version.
- Test clustering, grain storage, reminders, and streams independently.
Use the repository migration directories for clustering, persistence, and reminders. Select the scripts for your database and apply them in version order.
The client-library switch doesn’t itself change your grain-state payload format. It can change connection defaults and authentication behavior, so validate connection encryption, certificates, authentication, retry policy, and transaction behavior in staging.
Preserve serialization and state compatibility
Section titled “Preserve serialization and state compatibility”No Orleans 9-to-10 migration step requires renumbering IdAttribute values or rewriting state. Preserve the existing contract:
- Don’t reuse or renumber IdAttribute values.
- Keep AliasAttribute values stable when types or assemblies move.
- Don’t reorder record primary-constructor parameters used as implicit serializer IDs.
- Keep the configured grain-storage serializer unchanged during the runtime upgrade.
- Read representative old state, write it with Orleans 10, and verify that the rollback build can still read it before allowing production writes.
- Apply ADO.NET schema scripts in order and verify rollback compatibility before applying any irreversible script.
For the version-tolerance rules, see Orleans serialization.
Confirm hosting, placement, timers, and filters
Section titled “Confirm hosting, placement, timers, and filters”An Orleans 9 application already using CreateApplicationBuilder, UseOrleans, or UseOrleansClient doesn’t need a hosting rewrite.
Orleans 9.2 made ResourceOptimizedPlacement the default. If the production cluster still relies on RandomPlacement, make that policy explicit:
public static void KeepRandomPlacement(ISiloBuilder siloBuilder){ siloBuilder.Services.AddSingleton<PlacementStrategy, RandomPlacement>();}Continue using RegisterGrainTimer. When preserving behavior from the old RegisterTimer API, set Interleave to true; the new API defaults to non-interleaving callbacks.
public override Task OnActivateAsync(CancellationToken cancellationToken){ _timer = this.RegisterGrainTimer( callback: DoWorkAsync, options: new GrainTimerCreationOptions { DueTime = TimeSpan.FromSeconds(1), Period = TimeSpan.FromSeconds(10), Interleave = true });
return Task.CompletedTask;}
private static Task DoWorkAsync(CancellationToken cancellationToken) => Task.CompletedTask;Register call filters on the Orleans builders, not directly on IServiceCollection:
public static void ConfigureCallFilters(ISiloBuilder siloBuilder){ siloBuilder.AddIncomingGrainCallFilter(async context => { await context.Invoke(); });
siloBuilder.AddOutgoingGrainCallFilter<MyOutgoingCallFilter>();}Deploy and retain rollback
Section titled “Deploy and retain rollback”Follow Upgrade deployment and rollback. Use a separate Orleans 10 cluster by default. Keep the Orleans 9 cluster and its last compatible state recovery point until:
- Orleans 10 clients and silos have passed smoke and load tests.
- Provider data written by Orleans 10 is proven readable by the rollback build.
- No queued or streamed payload contains a type shape unavailable to Orleans 9.
- Metrics show stable activation placement, call latency, cancellation, reminder, and storage behavior.
Checklist
Section titled “Checklist”- Update to the latest Orleans 9.x patch and remove build warnings.
- Align every
Microsoft.Orleans.*package on one current 10.x patch. - Keep .NET 8 for the first deployment, or qualify the .NET 10 retarget separately.
- Remove UnorderedAttribute and replace valid OrleansConstructorAttribute uses.
- Set CancelRequestOnTimeout explicitly.
- Replace
System.Data.SqlClientand its invariant if SQL Server is used. - Preserve serializer IDs, aliases, and grain-storage serializer settings.
- Confirm the intended placement strategy, timer interleaving, and call-filter registration.
- Validate provider schemas and representative persisted state.
- Prepare and rehearse a parallel-cluster deployment and rollback.
