---
title: Workflows
description: Durable multi-step functions with checkpointing, parallel execution, and event waiting.
---

Workflows are durable, multi-step Go functions. Dispatch checkpoints each completed step so that if the process restarts mid-workflow, execution resumes from the last completed step — not from the beginning.

## Defining a workflow

```go
import "github.com/xraph/dispatch/workflow"

type OrderInput struct {
    OrderID      string  `json:"order_id"`
    Amount       float64 `json:"amount"`
    CustomerID   string  `json:"customer_id"`
    PaymentToken string  `json:"payment_token"`
}

var ProcessOrder = workflow.NewWorkflow("process_order",
    func(wf *workflow.Workflow, input OrderInput) error {
        if err := wf.Step("validate", func() error {
            return validateOrder(input.OrderID)
        }); err != nil {
            return err
        }

        if err := wf.Step("charge", func() error {
            return chargeCard(input.PaymentToken, input.Amount)
        }); err != nil {
            return err
        }

        return wf.Step("fulfill", func() error {
            return fulfillOrder(input.OrderID)
        })
    },
)
```

## Registering a workflow

```go
engine.RegisterWorkflow(eng, ProcessOrder)
```

## Starting a workflow

```go
engine.StartWorkflow(ctx, eng, ProcessOrder, OrderInput{
    OrderID: "ORD-001",
    Amount:  99.99,
})
```

## Steps

`wf.Step(name, fn)` executes `fn` and persists a checkpoint. If the workflow is re-executed (after a crash or restart), a step with an existing checkpoint is **skipped** and its stored result is returned.

This guarantees that side effects (HTTP calls, DB writes, email sends) happen exactly once across process restarts.

## Parallel steps

Run independent steps concurrently:

```go
if err := wf.Parallel(
    func() error { return sendConfirmationEmail(input.CustomerID) },
    func() error { return updateInventory(input.OrderID) },
    func() error { return notifyWarehouse(input.OrderID) },
); err != nil {
    return err
}
```

`Parallel` fails fast if any step returns an error. All non-failed goroutines complete before the error is returned.

## Waiting for events

A workflow can pause until an external event arrives:

```go
payload, err := wf.WaitForEvent(ctx, "payment.confirmed", 24*time.Hour)
if err != nil {
    return err // timeout or context cancelled
}
```

To trigger the event from outside:

```go
engine.TriggerEvent(ctx, eng, runID, "payment.confirmed", confirmationPayload)
```

## Sleeping

Pause execution for a duration (persists across restarts):

```go
if err := wf.Sleep(ctx, 30*time.Minute); err != nil {
    return err
}
```

## Run states

| State | Meaning |
|-------|---------|
| `running` | Workflow is executing |
| `completed` | All steps finished successfully |
| `failed` | A step failed terminally |
