Skip to main content
A workflow is a function that describes a multi-step process — like processing an order, onboarding a new user, or syncing data with an external service. What makes it special is that it’s durable: OpenWorkflow saves the progress of each step to the database. If the process crashes or the server restarts, the workflow picks up right where it left off instead of starting over.

Defining a Workflow

Define a workflow with defineWorkflow:
A workflow consists of:
  1. A spec - Configuration including the workflow name and optional version
  2. A function - The async function that contains your workflow logic

Running a Workflow

Start a workflow by calling ow.runWorkflow() with the workflow’s spec:
ow.runWorkflow() returns a handle immediately. The actual workflow execution happens in a worker process. This lets your application continue without waiting for the workflow to complete.
If you define a workflow with ow.defineWorkflow(...) instead, it returns a runnable workflow that supports .run(...) directly.

Scheduling a Workflow Run

You can schedule a workflow run for a specific time by passing availableAt:
You can also pass a duration string using the same duration format as step.sleep:
The run stays pending until availableAt is reached, then workers can claim it. If availableAt is in the past, the run is immediately available.

Waiting for Results

If you need to wait for a workflow to complete, use .result() on the handle:
result() polls the database periodically. Use this for workflows that complete quickly (seconds to minutes). For long-running workflows, consider using events or callbacks instead.
You can also configure a custom timeout:

Workflow Options

Name (Required)

Every workflow needs a unique name. This name is used to identify the workflow in the database and must match when workers execute the workflow.

Version (Optional)

Use versioning when you need to support multiple implementations of the same workflow simultaneously. See Versioning for details.

Schema (Optional)

Validate inputs before the workflow is enqueued using any Standard Schema compatible validator. See Standard Schema for details.

Retry Policy (Optional)

Control backoff and retry limits for this workflow:
Any retryPolicy fields you omit fall back to defaults. See Retries for the full behavior and defaults.

Idempotency Key (Optional)

You can prevent duplicate run creation by providing an idempotency key, though there is a performance cost to checking for duplicates, so use this only when necessary:
Within a given namespace, when an existing run matches the same workflowName + idempotencyKey, OpenWorkflow returns that existing run immediately. This dedupe window is built-in and lasts 24 hours from the original run creation time. The same idempotencyKey used in a different namespace will create a separate run.

Workflow Function Parameters

The workflow function receives an object with four properties:

Workflow Run States

A workflow run progresses through these states:

Determinism

New to workflow engines? This is the most important rule to understand. It’s simple once you know why it exists.
When a workflow resumes after a crash, OpenWorkflow replays it from the beginning. Completed steps return their saved results instantly, so no work is repeated. But for this to work, the workflow must take the same path every time it runs with the same inputs — it must be deterministic. This means you should avoid putting non-deterministic operations (like API calls, random numbers, or the current time) directly in the workflow body. Instead, wrap them in steps so their results are saved and replayed consistently.
Avoid calling Math.random(), Date.now(), or making API calls directly in the workflow function, since those change on each run, meaning they are non-deterministic. Wrap them in steps instead.