Skip to content

Workflow Versioning

Workflow definitions support versioning. When you publish a new version, the old version is deactivated and existing instances continue running on their pinned version.

Publishing a New Version

php
use Workflowable\Workflowable\Models\Workflow;
use Workflowable\Workflowable\Support\DataTransferObjects\WorkflowDefinition;

// Create the initial version
$v1 = Workflow::create([
    'name' => 'order_approval',
    'definition' => [...],
    'is_active' => true,
]);

// Publish v2 (deactivates v1 automatically)
$v2 = $v1->publish(WorkflowDefinition::fromArray([
    'name' => 'order_approval',
    'initial_step' => 'new_first_step',
    'steps' => [...],
    'transitions' => [...],
]));

The publish() method:

  1. Deactivates all active versions with the same name
  2. Determines the next version number from the highest existing version
  3. Creates a new Workflow row with the new definition
  4. Copies metadata (description, event_name, created_by) from the source

Instance Pinning

Workflow instances are pinned to a specific version via the workflow_id foreign key. When you publish a new version:

  • Existing instances continue executing on their original version's definition
  • New instances are created against the latest active version

This means you can safely deploy definition changes without affecting in-flight workflows.

Querying Versions

php
// Get all versions of a workflow (newest first)
$versions = Workflow::versionsOf('order_approval')->get();

// Get only the latest active version
$latest = Workflow::latestVersion('order_approval')->first();

// Check if a newer version exists
$v1->hasNewerVersion(); // true

// Get the latest version from any version
$latest = $v1->latestVersion(); // Returns the newest Workflow model

Artisan Command

List all versions of a workflow:

bash
php artisan workflowable:versions order_approval

Output includes version number, active status, step count, instance count, and creation date.

Best Practices

  • Always use publish() rather than manually creating versioned rows -- it handles deactivation and version numbering
  • Test new definitions before publishing to production
  • Monitor in-flight instances on old versions via workflowable:status --workflow=order_approval
  • The compound unique constraint on (name, version) prevents duplicate version numbers