Skip to main content
Child workflows allow you to execute one workflow from within another, creating hierarchical workflow compositions. This pattern is useful for breaking down complex business logic into smaller, reusable workflow components.

Overview

Child workflows execute independently but are managed by their parent workflow. They inherit certain properties from the parent (like queue and connection settings) but maintain their own execution state and history.

Basic Usage

Use the child() helper function to execute a child workflow:
use Workflow\Workflow;
use function Workflow\{child, activity};

class OrderWorkflow extends Workflow
{
    public function execute($orderId)
    {
        // Execute child workflow
        $paymentResult = yield child(PaymentWorkflow::class, $orderId);
        
        // Execute activity after child completes
        $result = yield activity(FulfillOrderActivity::class, $orderId);
        
        return $result;
    }
}

Multiple Child Workflows

You can execute multiple child workflows sequentially or in parallel:

Sequential Execution

public function execute()
{
    $result1 = yield child(FirstWorkflow::class);
    $result2 = yield child(SecondWorkflow::class, $result1);
    $result3 = yield child(ThirdWorkflow::class, $result2);
    
    return $result3;
}

Parallel Execution

use Workflow\ChildWorkflowStub;

public function execute($orderIds)
{
    $promises = [];
    
    foreach ($orderIds as $orderId) {
        $promises[] = child(ProcessOrderWorkflow::class, $orderId);
    }
    
    // Wait for all child workflows to complete
    $results = yield ChildWorkflowStub::all($promises);
    
    return $results;
}
Child workflows can also be executed in parallel using the all() helper function from the Workflow namespace.

Passing Options

Child workflows inherit the parent’s queue and connection settings by default, but you can override them:
use Workflow\WorkflowOptions;

public function execute()
{
    $options = new WorkflowOptions(
        connection: 'redis',
        queue: 'high-priority'
    );
    
    $result = yield child(
        ImportantWorkflow::class,
        $param1,
        $param2,
        $options
    );
    
    return $result;
}

Child Workflow Lifecycle

1

Parent yields child

The parent workflow yields a child workflow using child()
2

Child starts

The child workflow is created and started with the provided arguments
3

Parent waits

The parent workflow pauses execution and waits for the child to complete
4

Child completes

The child workflow executes and completes (or fails)
5

Parent resumes

The parent workflow resumes with the child’s result

Signaling Child Workflows

You can send signals to child workflows from the parent:
public function execute()
{
    // Start a long-running child workflow
    $childPromise = child(LongRunningWorkflow::class);
    
    // Get the child workflow instance
    $childWorkflow = WorkflowStub::find($childWorkflowId);
    
    // Send a signal to the child
    $childWorkflow->updateStatus('Processing');
    
    // Wait for child to complete
    $result = yield $childPromise;
    
    return $result;
}

Error Handling

If a child workflow fails, the exception is propagated to the parent:
public function execute()
{
    try {
        $result = yield child(RiskyWorkflow::class);
    } catch (\Exception $e) {
        // Handle child workflow failure
        yield activity(LogErrorActivity::class, $e->getMessage());
        
        // Optionally retry with different parameters
        $result = yield child(FallbackWorkflow::class);
    }
    
    return $result;
}

Use Cases

Decomposition

Break complex workflows into smaller, manageable pieces

Reusability

Reuse common workflow patterns across multiple parent workflows

Isolation

Isolate failure domains - child failures don’t automatically fail the parent

Fan-out

Process multiple items in parallel using child workflows

Best Practices

Each child workflow should have a single, well-defined responsibility. This makes them easier to test and reuse.
Don’t create child workflows for trivial operations - use activities instead. Child workflows are best for complex, multi-step processes.
Always consider how child workflow failures should be handled in the parent. Use try-catch blocks or saga patterns as needed.
Avoid deeply nested child workflows (more than 2-3 levels) as they can become difficult to debug and monitor.
  • Signals - Communicate with child workflows
  • Sagas - Handle failures across multiple workflows
  • Continue as New - Manage long-running workflows

Build docs developers (and LLMs) love