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.

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:

  1. Parallel Operation: Run V2 and V3 systems side-by-side, allowing V2 workflows to complete while starting new workflows in V3

  2. Incremental Migration: Migrate workflows in phases, starting with simpler workflows

  3. 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 Elsa meta-package includes Elsa.Api.Common, Elsa.Mediator, Elsa.Workflows.Core, Elsa.Workflows.Management, and Elsa.Workflows.Runtime

  • Persistence packages renamed: Elsa.Persistence.* → Elsa.EntityFrameworkCore.*

  • .NET 8+ required (no longer supports .NET Standard 2.0)

Namespace Changes

Common Namespace Mappings

V2 Namespace
V3 Namespace

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:

  1. Base Class:

    • V2: Activity base class

    • V3: Activity or CodeActivity (CodeActivity auto-completes)

  2. Execute Method:

    • V2: OnExecute or OnExecuteAsync returning IActivityExecutionResult

    • V3: ExecuteAsync or Execute (for CodeActivity)

  3. Completion:

    • V2: Return Done(), Outcome(), etc.

    • V3: Call await context.CompleteActivityAsync() (or automatic with CodeActivity)

  4. Attributes:

    • V2: [Activity] with separate Category parameter

    • V3: [Activity] with namespace, category, and description

  5. Input Properties:

    • V2: Simple types with [ActivityInput]

    • V3: Wrapped in Input<T> with [Input]

  6. 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 → ExecuteAsync

  • Must 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 block

  • V3: Call context.CreateBookmark(payload) to block

  • V3: No separate OnResume method; execution continues after bookmark is resumed

Trigger Activities

V2 Trigger Activity

V3 Trigger Activity

Key Changes:

  • V3: Inherit from Trigger base class

  • V3: Check context.IsTriggerOfWorkflow() to handle trigger vs resumption

  • V3: Implement GetTriggerPayload to 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

Aspect
V2
V3

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

  1. Add Root Container: Wrap all activities in a root object

  2. Update Activity Type Names: Add Elsa. prefix to all activity types

    • WriteLine → Elsa.WriteLine

    • Delay → Elsa.Delay

    • HttpEndpoint → Elsa.HttpEndpoint

    • SendHttpRequest → Elsa.Http.SendHttpRequest

  3. Convert Property Structure: Transform property arrays to direct properties

    V2:

    V3:

  4. Update Connection Structure: Change to nested source/target format

    V2:

    V3:

  5. Add Required Metadata: Include new V3 fields

Expression Type Mapping

V2 Expression Syntax
V3 Expression Type

Literal

Literal

JavaScript

JavaScript

Liquid

Liquid

Json

Object

Programmatic Workflows

V2 Programmatic Workflow

V3 Programmatic Workflow

Key Changes:

  • V2: Implement IWorkflow and use fluent API with StartWith/Then

  • V3: Inherit from WorkflowBase and build activity tree directly

  • V3: More explicit activity composition with builder.Root

  • V3: 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:

  1. Parallel Databases: Use separate databases for V2 and V3

  2. Let V2 Complete: Allow existing V2 workflows to finish naturally

  3. Fresh Start in V3: Create new workflow instances in V3

Database-level migration is complex and error-prone. Most teams run V2 and V3 in parallel until V2 workflows complete.

V2 Persistence Configuration

V3 Persistence Configuration

Key Changes:

  • Separate persistence configuration for management and runtime

  • Different method names: UseEntityFrameworkPersistence → UseEntityFrameworkCore

  • More explicit control over what gets persisted

Supported Providers

Provider
V2 Package
V3 Package

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.Job for background activities

  • Hangfire 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

  1. Unit Test Custom Activities

  2. Integration Test Workflows

  3. 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:

  1. ✅ No automated migration path exists

  2. ✅ Custom activities must be rewritten

  3. ✅ Workflow JSON must be transformed

  4. ✅ Database schemas are incompatible

  5. ✅ Plan for parallel operation during transition

  6. ✅ V3 offers significant improvements in scalability and performance

  7. ✅ Built-in background scheduler eliminates need for Hangfire in basic scenarios

  8. ✅ 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