This release focuses on Flowchart execution improvements, stronger runtime correctness, major test coverage expansion, reliability fixes for scheduling/triggers and HTTP content handling, and a platform upgrade to .NET 10 while retaining support for .NET 8 and .NET 9.
Highlights
Token-centric Flowchart execution model with configurable MergeMode, plus multiple refinements and DI-based configuration (opt-in). See Flowchart: token-based execution + per-activity MergeMode. (PRs: #6632, #6937, #6993, #7141)
Upgrade to .NET 10 across the solution (with conditional compatibility dependencies where needed). (PR: #7062)
and a major expansion of unit/integration/component test coverage across core activities, scheduling, HTTP endpoints, JavaScript, and flowchart execution. (PR: #6719 and many follow-ups)
New Activity Testing API
Improved runtime observability & execution record serialization, including snapshots and a new ActivityCompleted notification. (PRs: #6675, #6800, #6807)
Elsa 3.6.0 introduces an optional token-based execution algorithm for the Flowchart activity. Instead of relying on the previous counter-based scheduling model, the Flowchart can now track progress using tokens that represent a taken connection (from a source activity outcome to a target activity).
When an activity completes, the flowchart:
Emits tokens for each taken outbound connection (based on the activity’s outcome names).
Consumes inbound tokens that were waiting for the completed activity.
Schedules downstream activities based on each target activity’s MergeMode.
New: MergeMode (configurable per activity)
With token-based execution enabled, Flowchart supports a new MergeMode concept that determines how a node behaves when it has multiple inbound connections. You can now specify a merge mode per activity, allowing different “join” semantics within the same flowchart.
In broad terms, merge modes enable behaviors like:
Stream-like behavior: proceeds without strict joining, helping avoid dead-path waiting.
Forward-join behavior (Merge): waits for tokens from all forward inbound connections (loop/back edges don’t block).
Strict join behavior (Converge): waits for tokens from all inbound connections, including loop/back edges.
First-arrival behavior (Cascade / Race): schedules on the first arriving inbound token; in Race mode, other inbound ancestors are canceled so only the “winning” path continues.
This improves predictability for joins, forks, and cyclic graphs, while giving you fine-grained control over how each activity merges incoming paths.
How to opt in (Program.cs)
Token-based Flowchart execution is opt-in. Enable it via the Flowchart feature configuration:
These are the changes most likely to affect upgrades from 3.5.x.
1) Multi-targeting: .NET 8, .NET 9, and .NET 10
Elsa 3.6.0 multi-targets .NET 8, .NET 9, and .NET 10.
Most consumers can continue targeting .NET 8 or .NET 9.
If you build Elsa from source (or run CI against the full repo), ensure your build agents have a .NET 10 SDK available. (PR: #7062)
2) Package / project renames
Some projects / packages have been renamed. Make sure to update your package references accordingly.
In most cases, this also impacted the root namespace of these packages, so update using statements and fully-qualified type names as needed.
Migration tips
Start by updating NuGet references (e.g., in .csproj, Directory.Packages.props, Directory.Build.props).
Then update namespaces/usages:
A simple approach is a solution-wide search/replace for the old root namespaces (e.g. Elsa.EntityFrameworkCore → Elsa.Persistence.EFCore).
If you have global usings, update those too.
If you use central package management, ensure only the new package IDs remain (to avoid restore conflicts).
Optional commands (adjust paths as needed):
# If you want a quick way to find old package IDs/usings in your codebase:
rg "Elsa\\.(EntityFrameworkCore|Dapper|MongoDb|Elasticsearch|Webhooks|CSharp|Dsl|JavaScript|Liquid|Python|Kafka|MassTransit|FileStorage|Hangfire|Quartz)" -S
# Restore/build after updates:
dotnet restore --ignore-failed-sources
DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet build
SQL activities removed from Core. If you used SQL activities, reference the appropriate extension package(s) instead of relying on core-only dependencies. (PR: #6625)
IO module moved to Extensions. If you depended on IO activities/types from core, update references to the new extension location. (PR: #6835)
Persistence and integration packages renamed. If you referenced these packages previously, update your package references accordingly:
Database extensions were refactored and migration support for v3.6 was added. Review persistence configuration and apply migrations where applicable. (PRs: #6788, #6931)
5) Flowchart execution semantics
The token-centric Flowchart model and merge-mode changes can affect execution semantics in complex graphs (especially joins/loops/cycles). Re-test those workflows after upgrading. See Flowchart: token-based execution + per-activity MergeMode. (PRs: #6632, #6937, #6993, #7141)
6) Breaking change: duplicate triggers now prevent startup (PR: #7131)
Starting with 3.6.0-rc1, Elsa performs stricter validation of persisted triggers.
If your database contains duplicate trigger records (typically caused by concurrency/race conditions in multi-engine environments prior to the fix in PR #7131), the application can fail to start until those duplicates are removed.
Action required: Before upgrading, scan for and remove duplicate triggers from your triggers table.
Sample SQL: de-dupe trigger records (generic template)
⚠️ Review and test in a non-production environment first. Take a backup before running any DELETE.
This script keeps the first row per “duplicate key” group and deletes the rest.
You must replace:
WorkflowTriggers with your actual triggers table name, and
the PARTITION BY (...) columns with the set of columns that define “uniqueness” for your trigger records (often things like tenant/workflow definition/version/activity/trigger type/hash/route, depending on your provider schema).
BEGIN TRANSACTION;
-- 1) Inspect duplicates (adjust columns to match your schema)
WITH d AS (
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY
TenantId,
WorkflowDefinitionId,
ActivityId,
Name,
Hash
ORDER BY Id
) AS rn
FROM WorkflowTriggers
)
SELECT *
FROM d
WHERE rn > 1
ORDER BY TenantId, WorkflowDefinitionId, ActivityId, Name, Hash, Id;
-- 2) Delete duplicates (keeps rn = 1)
WITH d AS (
SELECT
Id,
ROW_NUMBER() OVER (
PARTITION BY
TenantId,
WorkflowDefinitionId,
ActivityId,
Name,
Hash
ORDER BY Id
) AS rn
FROM WorkflowTriggers
)
DELETE FROM WorkflowTriggers
WHERE Id IN (SELECT Id FROM d WHERE rn > 1);
COMMIT;
---
## Recommended verification checklist
After upgrading, we recommend validating the following areas:
- **Flowcharts** using joins, loops, and cyclic graphs (FlowJoin/WaitAny, merge modes). (#6592, #6632, #6937, #7151)
- **Scheduling & cron triggers**, especially fast schedules / edge cases. (#6641, #7047, #7045)
- **Multi-engine environments** for trigger registration correctness (no duplicates). (#7131)
- **HTTP activities**: Content-Type/charset handling and Content-Length correctness; file upload/download scenarios. (#6676, #7027, #7094, #7125)
- **Persistence**: migration path and EF Core provider configuration in your target environment. (#6788, #6931)
---
## What’s Changed
### Flowchart & core execution
- Fix unexpected FlowJoin(WaitAny) behavior in cyclic flow. (PR: #6592)
- Introduce token-centric Flowchart execution model with configurable MergeMode. (PR: #6632)
- Refactor flowchart token handling and enhance merge mode behavior. (PR: #6937)
- Refactors and clarifies Flowchart merge modes. (PR: #6993)
- Configures Flowchart Execution via DI. (PR: #7141)
- Fix `Switch` activity behavior and improve testing utilities. (PR: #7151)
- Improves Fork activity and break signal handling. (PR: #7104)
- Add missing `Pending` state to `ActivityStatus` enum. (PR: #6856)
### Workflow composition, scripting & developer hooks
- Add optional workflow output flag. (PR: #6659)
- Add `ActivityCompleted` notification for workflow activity completion. (PR: #6675)
- Fix Liquid expressions not working in sub-workflows (workflow-as-activity). (PR: #6678)
- Allow C# Script to use dot notation with `ExpandoObject` (JSON variables). (PR: #6689)
- Search for workflow-as-activities based on DefinitionId (not only VersionId). (PR: #7149)
- Add Elsa Script DSL. (PR: #7076)
- Add bus configurator hook to `MassTransitFeature`. (PR: #6658)
- Workflow input as activity input. (PR: #6910)
### HTTP, endpoints & content handling
- Fix Content-Type header charset auto-appending in HTTP requests. (PR: #6676)
- Fix Content-Length mismatch by reworking `RawStringContent`. (PR: #7027)
- Update `RawStringContent` encoding in `JsonContentFactory`. (PR: #6786)
- Fix wrong strategy selection for some string content. (PR: #6777)
- Expose the first uploaded file. (PR: #7010)
- Better base64 evaluation + appropriate zip entry naming. (PR: #6783)
- Fix wrong naming in resulting entries when file is input from HTTP. (PR: #6806)
- Unit & integration tests for `DownloadHttpFile`. (PR: #7094)
- HTTP endpoint unit, integration and component tests. (PR: #7125)
### Triggers, scheduling & concurrency
- Trigger payload validation; refactor HttpEndpoint validator; add Cron validator. (PR: #6641)
- Fix cron triggers silently stopping when delay calculation returns zero. (PR: #7047)
- Fix semaphore release logic in scheduled task execution. (PR: #7045)
- Fix race condition causing duplicate trigger registration in multi-engine environments + add concurrency regression tests. (PR: #7131)
- Extensive unit and component tests for scheduling activities. (PR: #7036)
### Persistence, database & migrations
- Refactor database extensions and support migrations for v3.6. (PR: #6788)
### Serialization, conversion & correctness
- Add `FuncExpressionValueConverter` for JSON serialization. (PR: #6607)
- Introduce activity execution record capturing and serialization improvements. (PR: #6800)
- Refactor activity execution record serialization with snapshots. (PR: #6807)
- Add `IEnumerableTypeConverter`. (PR: #7020)
- Add `IAsyncEnumerable` check to `GetItemSource`. (PR: #6897)
- Parse `VariableTestValues` more robustly (ExpandoObject + type conversion). (PR: #6883)
- Use `FullName` in `WorkflowDictionary`. (PR: #6923)
- Add `ILoggerFactory` support to converters. (PR: #7153)
- Fix missing `DefaultValue` for `OuterBoundInclusive` in `For` activity. (PR: #6680)
### Platform / dependencies / repo organization
- Upgrade projects to target .NET 10; update project files for consistency; add conditional compatibility dependencies. (PR: #7062)
- Update Jint to 4.3.0. (PR: #6794)
- Enhanced `SasTokensFeature` to support sharing protected keys via shared drive, Redis cache, and other mechanisms. (PR: #6665)
- Realign Core and Extension repos. (PR: #6664)
- Add back SasToken project. (PR: #6673)
- Remove SQL activities from Core. (PR: #6625)
- Remove IO module from Core (moved to Extensions). (PR: #6835)
- Enhance thread safety with `ConcurrentDictionary` usage. (PR: #6760)
- Downgrade `JetBrains.Annotations` to fix package builds. (PR: #6848)
### Runtime stability / cleanup
- Fix `FileSystemWatcher` cleanup. (PR: #6657)
- Fix ASP.NET integration test crashes by adding proper Elsa background task shutdown. (PR: #6686)
- Fix `EventBase` child activity not executing `OnEventReceived`. (PR: #6687)
- Fix `ParentWorkflowInstanceId` not being set. (PR: #7029)
### UI / Studio / Designer
- View suspended workflow in studio fix. (PR: #6646)
- New UI hint: `RadioList` (API models + UI components + related refactors). (PRs: #6711, #6712, #6713, #6714)
- Generic activity name fix. (PR: #6698)
- Refactor `ActivityRegistry` to populate all activities in workflow edit. (PR: #6605)
- Fix: allow loading all descriptors in the UI. (PR: #6648)
### Testing (major coverage expansion)
> This release includes a large number of new tests across most core activities. Some representative additions:
- Implement Activity Testing API. (PR: #6719)
- Coverage enforcement for test projects. (PR: #6950)
- Code coverage configuration and test project adjustments. (PR: #7049)
- Integration tests for Flowchart. (PR: #6991)
- Integration tests for RunJavaScript + introduce `WorkflowTestFixture`. (PR: #7002)
- Integration tests for `WorkflowDefinitionActivity` scenarios. (PR: #6999)
- ExecuteWorkflow activity tests. (PR: #7003)
- BulkDispatchWorkflows tests and improved activity coverage. (PR: #7026)
- DispatchWorkflow tests with new workflow definitions. (PR: #7035)
- Integration tests for core activities. (PR: #7100)
- Many more unit & integration tests across core activities such as Container, Sequence, Start/End/Complete/Finish/Fault, ParallelForEach, Correlate, EventBase, Publish Event, and multiple flow activities. (Multiple PRs including: #6989, #6995–#6997, #7001, #7004, #7005, #7007, #7008, #7016, #7031, #7090, #7093, #7102, #7103, #7108–#7117, #7119–#7120, #7112)
### Misc / docs / polish
- Update `CommonTypesDefinitionProvider.cs`. (PR: #6615)
- Fix typo in README section title. (PR: #6629)
- Fix spelling in hosted service LogError messages. (PR: #6654)
- Fix duplicate words in XML comments. (PR: #6655)
---
## New Contributors
Thanks to our new contributors:
- @Nordran (PR: #6592)
- @mhichb (PR: #6615)
- @MaxBrooks114 (PR: #6607)
- @LaamiriOuail (PR: #6629)
- @zengande (PR: #6761)
- @FuJa0815 (PR: #6897)
- @mberthillot-flowwa (PR: #6910)
- @crashkonijn (PR: #7029)
- @j03y-nxxbz (PR: #7149)
- @Jelger-Quadira (PR: #7146)
---
## Full Changelog
- Compare view: https://github.com/elsa-workflows/elsa-core/compare/3.5.2...3.6.0-rc1