Skip to main content
Version: 2.x

Workflow ID

Instance IDs and Run IDs​

A durable workflow has two identifiers with different lifecycles:

  • The instance id (id(), workflowId()) is the stable public handle for the workflow. It is generated when the workflow is first started — or supplied by the caller — and never changes for the lifetime of that workflow, including across continue-as-new chains.
  • The run id (runId()) identifies one concrete execution generation of that workflow. It is newly allocated every time a new run is created, which happens on the first start and when the workflow continues as new.

Treat the instance id as the public, callable handle. Treat the run id as a pointer to a specific generation that is useful for inspection, debugging, or audit — not as something long-lived control-plane callers should track.

use Workflow\V2\WorkflowStub;

$workflow = WorkflowStub::make(MyWorkflow::class);

$id = $workflow->id();

$workflow->start();

$runId = $workflow->runId();

Use the id when you want the stable public handle for the workflow. Use the run id when you need to inspect one concrete execution.

Run ID Lifecycle​

A run id is an execution-generation identifier. Every v2 workflow generation has its own run id, and a single instance id can span many generations over time:

  • A fresh start() creates the first run and its first run id.
  • continueAsNew(...) closes the current run as completed / continued and starts a new run with a fresh run id under the same instance id. See Continue As New.

Because a run id belongs to one generation, callers that want durable behavior across those transitions should resolve by instance id:

  • Signals, queries, updates, and operator commands always resolve the newest durable run for an instance. Callers do not need to track run ids across continue-as-new boundaries.
  • Drill-down tools that pin a specific generation — for example Waterline's run-detail view, a history export, or a replay debugger — accept an explicit run id so they can inspect one execution in isolation.

The run id surfaces as runId() inside workflow code and activities, and as the workflow_run_id / run_id field on history, projections, and exports. It is always the run id of the generation that owns the event or row. Do not expect a run id recorded on older history events to equal the current run id of the same instance.

User-defined Instance IDs​

When starting a workflow you may optionally specify the id. User-defined ids must be URL-safe strings up to 191 characters using only letters, numbers, ., _, -, and :.

$workflow = WorkflowStub::make(MyWorkflow::class, 'order-123');

Later when you want to reference the workflow, you can load it with your custom id.

$workflow = WorkflowStub::load('order-123');

Choosing a caller-supplied ID​

Choose an ID that identifies one business operation consistently. Retrying the same start should reuse that ID; generate a new ID for a different operation. Include a workflow-type prefix and, when needed, an opaque tenant reference to avoid collisions between applications sharing a store. For example, order:tenant-7f2:01J9Z6K6Z2EPV5G0C3R8F4M9AN combines those prefixes with a collision-resistant identifier. A tenant prefix is a naming convention, not an authorization boundary. Configure namespace isolation separately.

The ID does not override the duplicate-start policy. The default rejects a duplicate start. ReturnExistingActive can return the existing active workflow without starting another run or replacing its original arguments. A completed instance's ID remains reserved; changing the workflow type does not make that ID available again.

IDs are visible metadata​

Instance IDs appear in plaintext in Waterline, URLs, CLI output, logs, history exports and the database. Payload codecs, including payload encryption, do not cover these identifiers. Use opaque references instead of email addresses, names, access tokens or other personal or secret data. Keep sensitive business details in payload fields protected by your application's data-handling policy. An unguessable ID does not replace authorization.

Accessing IDs Inside Activities and Workflows​

Inside an activity:

use Workflow\V2\Activity;

class MyActivity extends Activity
{
public function handle(): void
{
$id = $this->workflowId();
$runId = $this->runId();
}
}

Inside a workflow, $this->workflowId() returns the instance id and $this->runId() returns the selected run id for the currently executing run.