Skip to main content
Long-running workflows that pause for days or weeks often outlive the software release that initiated them. If workflow code changes while executions are suspended, resuming workflows must be done deterministically and safely. Siglo provides native workflow version tagging, compatibility enforcement, and state migration functions.

1. Declaring Workflow Versions

Assign semantic version identifiers to flows using .version() or execution options:
When suspended, the declared version ('2.1.0') is recorded in the wait record and storage checkpoint metadata.

2. Version Verification on Resumption

When resuming a workflow, resumeWorkflow compares the target workflow version with the recorded checkpoint version:
  • Matching Versions: If versions match (e.g. '2.1.0' === '2.1.0'), execution resumes immediately.
  • Mismatched Versions: If versions differ and no migration is declared, resumption fails safely with WorkflowVersionMismatchException.

3. State Migration Functions

To upgrade suspended workflows across code versions, supply migration mappings to flow.resume() or resumeWorkflow():

A. Version Transition Map (migrations: Record<string, MigrationFn>)

Target specific version jumps using the '<actualVersion>-><expectedVersion>' key syntax:

B. Unified Migration Function

Alternatively, provide a single function that handles multiple version transitions programmatically:

Checkpoint Storage Effect

When a migration function successfully transforms state during resumption:
  1. The transformed context replaces the legacy snapshot.
  2. The storage checkpoint revision counter is monotonically incremented.
  3. The checkpoint’s recorded version is updated to the targetVersion.

4. Deployment Best Practices

  1. Explicit Versioning: Always tag long-running workflows with .version('X.Y.Z').
  2. Backward-Compatible Step Names: Keep step identifiers consistent between releases so $steps references remain unbroken.
  3. Automated Migration Testing: Write unit tests using @siglo/testing to verify that state migration functions transform legacy fixtures into the exact shape expected by downstream steps in the new version before rolling code to production: