V2 to V3 Migration Guide
Complete migration guide from Elsa Workflows V2 to V3, covering breaking changes, custom activities, workflows, and concepts.
Overview
Elsa Workflows 3 is a complete rewrite of the library with significant architectural improvements for scalability, performance, and extensibility. This guide helps you migrate from Elsa V2 to V3.
Important: There is no automated migration path from V2 to V3. The internal representation of workflow definitions, activities, and properties has changed substantially. Manual recreation of workflows in V3 is required.
What's Changed
Complete rewrite with new execution model
New workflow JSON schema and structure
Updated custom activity implementation
Different NuGet package structure
New database schema
Improved background activity scheduler
Enhanced blocking activities and triggers
Migration Strategy
Given the scope of changes, consider these approaches:
Parallel Operation: Run V2 and V3 systems side-by-side, allowing V2 workflows to complete while starting new workflows in V3
Incremental Migration: Migrate workflows in phases, starting with simpler workflows
Fresh Start: For smaller implementations, recreate workflows from scratch in V3
Migration Checklist
Use this checklist to track your migration progress:
Preparation
Package Migration
Custom Activities
Workflow Definitions
Configuration
Testing
Deployment
Breaking Changes
NuGet Packages
V2 Package Structure
V3 Package Structure
Key Changes:
Consolidated packages: The
Elsameta-package includesElsa.Api.Common,Elsa.Mediator,Elsa.Workflows.Core,Elsa.Workflows.Management, andElsa.Workflows.RuntimePersistence packages renamed:
Elsa.Persistence.*→Elsa.EntityFrameworkCore.*.NET 8+ required (no longer supports .NET Standard 2.0)
Namespace Changes
Common Namespace Mappings
Elsa.Activities
Elsa.Workflows.Activities
Elsa.Services
Elsa.Workflows.Core / Elsa.Workflows.Runtime
Elsa.Models
Elsa.Workflows.Models
Elsa.Attributes
Elsa.Workflows.Attributes
Example Migration
V2:
V3:
Startup Configuration
V2 Configuration
V3 Configuration
Key Changes:
Separate management and runtime configuration
Explicit middleware registration
More granular control over features
Custom Activities Migration
Activity Implementation Changes
V2 Custom Activity
V3 Custom Activity
Key Differences:
Base Class:
V2:
Activitybase classV3:
ActivityorCodeActivity(CodeActivity auto-completes)
Execute Method:
V2:
OnExecuteorOnExecuteAsyncreturningIActivityExecutionResultV3:
ExecuteAsyncorExecute(for CodeActivity)
Completion:
V2: Return
Done(),Outcome(), etc.V3: Call
await context.CompleteActivityAsync()(or automatic with CodeActivity)
Attributes:
V2:
[Activity]with separate Category parameterV3:
[Activity]with namespace, category, and description
Input Properties:
V2: Simple types with
[ActivityInput]V3: Wrapped in
Input<T>with[Input]
Getting Input Values:
V2: Direct property access
V3:
Message.Get(context)
Activity with Outputs
V2 Activity with Output
V3 Activity with Output
Key Changes:
Outputs wrapped in
Output<T>Use
Result.Set(context, value)instead of direct assignment
Async Activities
V2 Async Activity
V3 Async Activity
Key Changes:
Method name:
OnExecuteAsync→ExecuteAsyncMust explicitly call
await context.CompleteActivityAsync()Use service location via
context.GetRequiredService<T>()instead of constructor injection
Blocking Activities
V2 Blocking Activity
V3 Blocking Activity
Key Changes:
V2: Return
Suspend()to blockV3: Call
context.CreateBookmark(payload)to blockV3: No separate
OnResumemethod; execution continues after bookmark is resumed
Trigger Activities
V2 Trigger Activity
V3 Trigger Activity
Key Changes:
V3: Inherit from
Triggerbase classV3: Check
context.IsTriggerOfWorkflow()to handle trigger vs resumptionV3: Implement
GetTriggerPayloadto return the bookmark payload for indexing
Activity Registration
V2 Registration
V3 Registration
Note: Registration pattern is similar, but uses the new builder pattern in V3.
Workflow JSON Migration
V2 Workflow JSON Structure
V3 Workflow JSON Structure
Key JSON Schema Changes
Root Container
Activities listed directly
Activities wrapped in root object (Flowchart, Sequence)
Activity Types
Simple names: "WriteLine"
Fully qualified: "Elsa.WriteLine"
Properties
Array of property objects
Direct properties on activity with expression wrappers
Property Structure
properties[].name with expressions object
Direct property with typeName and expression
Connections
sourceActivityId / targetActivityId
Nested source/target objects with activity and port
Metadata
Basic id, version, isPublished
Additional definitionId, isLatest
Migration Steps for JSON
Add Root Container: Wrap all activities in a
rootobjectUpdate Activity Type Names: Add
Elsa.prefix to all activity typesWriteLine→Elsa.WriteLineDelay→Elsa.DelayHttpEndpoint→Elsa.HttpEndpointSendHttpRequest→Elsa.Http.SendHttpRequest
Convert Property Structure: Transform property arrays to direct properties
V2:
V3:
Update Connection Structure: Change to nested source/target format
V2:
V3:
Add Required Metadata: Include new V3 fields
Expression Type Mapping
Literal
Literal
JavaScript
JavaScript
Liquid
Liquid
Json
Object
Programmatic Workflows
V2 Programmatic Workflow
V3 Programmatic Workflow
Key Changes:
V2: Implement
IWorkflowand use fluent API withStartWith/ThenV3: Inherit from
WorkflowBaseand build activity tree directlyV3: More explicit activity composition with
builder.RootV3: Activities instantiated directly instead of using extension methods
Workflow with Variables
V2 Workflow with Variables
V3 Workflow with Variables
Key Changes:
Variable declaration syntax similar but initialization improved
Setting variables uses direct property assignment instead of fluent methods
Accessing variables uses same
counter.Get(context)pattern
Database and Persistence
Schema Changes
The database schema has changed significantly between V2 and V3:
Table names and structures are different
Workflow instance data serialization format changed
No automated migration scripts available
Recommended Approach:
Parallel Databases: Use separate databases for V2 and V3
Let V2 Complete: Allow existing V2 workflows to finish naturally
Fresh Start in V3: Create new workflow instances in V3
V2 Persistence Configuration
V3 Persistence Configuration
Key Changes:
Separate persistence configuration for management and runtime
Different method names:
UseEntityFrameworkPersistence→UseEntityFrameworkCoreMore explicit control over what gets persisted
Supported Providers
SQL Server
Elsa.Persistence.EntityFramework.SqlServer
Elsa.EntityFrameworkCore.SqlServer
PostgreSQL
Elsa.Persistence.EntityFramework.PostgreSql
Elsa.EntityFrameworkCore.PostgreSql
MySQL
Elsa.Persistence.EntityFramework.MySql
Elsa.EntityFrameworkCore.MySql
SQLite
Elsa.Persistence.EntityFramework.Sqlite
Elsa.EntityFrameworkCore.Sqlite
MongoDB
Elsa.Persistence.MongoDb
Elsa.MongoDb
Background Job Scheduler
V2 Job Scheduling
In V2, background activities required external job scheduler like Hangfire:
V3 Job Scheduling
V3 includes a built-in background activity scheduler using .NET Channels:
Key Changes:
Built-in scheduler eliminates need for Hangfire in basic scenarios
Use
ActivityKind.Jobfor background activitiesHangfire still supported for advanced scenarios (failover, distributed execution)
Common Migration Pitfalls
1. Direct JSON Import
Problem: Attempting to import V2 workflow JSON directly into V3.
Solution: V2 and V3 use incompatible JSON schemas. You must:
Export V2 workflows as JSON
Transform the JSON structure to V3 format
Update all activity type names to fully qualified names
Test thoroughly before importing
2. Assuming API Compatibility
Problem: Expecting V2 APIs to work in V3 with minor changes.
Solution: V3 is a complete rewrite. Expect to rewrite:
Custom activities completely
Workflow definitions
Integration points
Extension implementations
3. Database Migration
Problem: Trying to migrate the database schema from V2 to V3.
Solution:
Use separate databases for V2 and V3
Run systems in parallel during transition
Let V2 workflows complete naturally
Start new workflows in V3
4. Constructor Injection in Activities
Problem: Using constructor injection in custom activities.
V2 Pattern (worked but discouraged):
V3 Solution (service location):
Reason: Service location makes activity instantiation easier in workflow definitions.
5. Forgetting Activity Completion
Problem: Not calling CompleteActivityAsync in V3 activities.
Incorrect:
Correct:
Or use CodeActivity:
6. Input/Output Property Access
Problem: Accessing Input<T> and Output<T> properties directly.
Incorrect:
Correct:
7. Bookmark Resumption
Problem: Using V2 bookmark/resumption patterns in V3.
V2 Pattern:
V3 Pattern:
8. Missing Root Container in JSON
Problem: V2-style JSON without root container fails to parse in V3.
Solution: Always wrap activities in a root container:
9. Incorrect Package References
Problem: Mixing V2 and V3 packages.
Solution: Ensure all Elsa packages are V3:
10. Trigger Activity Implementation
Problem: Not checking IsTriggerOfWorkflow() in trigger activities.
Incorrect:
Correct:
Testing and Validation
Testing Strategy
Unit Test Custom Activities
Integration Test Workflows
Test JSON Workflows
Validation Checklist
Migration Timeline Example
Phase 1: Preparation (Week 1-2)
Set up V3 development environment
Inventory all V2 workflows and custom activities
Review V3 documentation
Create proof-of-concept migrations
Phase 2: Custom Activities (Week 3-4)
Rewrite all custom activities for V3
Unit test each activity
Register activities with V3 engine
Phase 3: Workflow Migration (Week 5-8)
Convert workflow definitions to V3
Test each workflow individually
Migrate programmatic workflows
Update integration points
Phase 4: Infrastructure (Week 9-10)
Set up V3 database schema
Configure persistence providers
Deploy V3 application to staging
Configure monitoring and logging
Phase 5: Parallel Operation (Week 11-12)
Run V2 and V3 side-by-side
Monitor both systems
Route new workflows to V3
Allow V2 workflows to complete
Phase 6: Cutover (Week 13)
Verify all V2 workflows completed
Decommission V2 system
Full production deployment of V3
Monitor and optimize
Resources
Documentation
GitHub Resources
Community
Summary
Migrating from Elsa V2 to V3 requires significant effort due to the complete rewrite:
Key Takeaways:
✅ No automated migration path exists
✅ Custom activities must be rewritten
✅ Workflow JSON must be transformed
✅ Database schemas are incompatible
✅ Plan for parallel operation during transition
✅ V3 offers significant improvements in scalability and performance
✅ Built-in background scheduler eliminates need for Hangfire in basic scenarios
✅ More explicit and type-safe API
Migration Approach:
Start with a comprehensive inventory of V2 assets
Rewrite custom activities using V3 patterns
Transform workflow definitions to V3 format
Run V2 and V3 in parallel during transition
Thoroughly test all migrated components
Monitor carefully during cutover
While migration requires significant effort, V3's improvements in architecture, performance, and extensibility make it worthwhile for long-term success.
Last updated